自定義 View(如自繪時鐘、滑塊、圖表)內部狀態頻繁變化,需實時通知外部 Activity/Fragment 更新 UI(如底部 TextView 顯示當前時間)。傳統接口回調寫法耦合度高,廣播機制可實現解耦。
public class ClockView extends View {
private Context mContext; // 持有 Activity Context
private BroadcastReceiver timeReceiver; // 可選:接收外部廣播
public ClockView(Context context) {
super(context);
this.mContext = context;
}
public ClockView(Context context, AttributeSet attrs) {
super(context, attrs);
this.mContext = context;
}
// 內部狀態變化時發送廣播
private void notifyTimeChanged(String timeStr) {
Intent intent = new Intent("com.example.ACTION_TIME_UPDATE");
intent.putExtra("time", timeStr);
mContext.sendBroadcast(intent); // 關鍵:使用持有的 Context 發送
}
// 可選:註冊接收外部廣播
public void registerReceiver() {
timeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 處理外部指令
}
};
IntentFilter filter = new IntentFilter("com.example.ACTION_CONTROL");
mContext.registerReceiver(timeReceiver, filter);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (timeReceiver != null) {
mContext.unregisterReceiver(timeReceiver); // 防洩漏
}
}
}
// 發送
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
// 註冊
LocalBroadcastManager.getInstance(mContext).registerReceiver(receiver, filter);
// 註銷
LocalBroadcastManager.getInstance(mContext).unregisterReceiver(receiver);
✅ 優勢:不跨進程、效率高、安全性好(不被其他 App 接收)。
⚠️ 注意:AndroidX 版本需引入 `androidx.localbroadcastmanager:localbroadcastmanager:1.1.0`。
public interface OnTimeChangeListener {
void onTimeChanged(String time);
}
public class ClockView extends View {
private OnTimeChangeListener listener;
public void setOnTimeChangeListener(OnTimeChangeListener listener) {
this.listener = listener;
}
private void notify(String time) {
if (listener != null) listener.onTimeChanged(time);
}
}
// Activity 中
clockView.setOnTimeChangeListener(time -> tvTime.setText(time));
💡 選型建議: 同一組件內、一對一通信用接口;跨組件、一對多、跨進程用廣播/EventBus/LiveData。
| 坑點 | 後果 | 修正 |
|---|---|---|
| 使用 `getApplicationContext()` 發送廣播 | 無法發送有序廣播、權限校驗失效 | 必須使用 Activity/Service Context(構造方法傳入的 `context` 即可) |
| 靜態持有 Context | 嚴重內存洩漏 | 實例字段持有,`onDetachedFromWindow` 釋放 |
| 未註銷廣播接收器 | 內存洩漏、崩潰 | 配對 `register/unregister`,或用 LocalBroadcastManager |
| 隱式 Intent 未導出 | Android 8.0+ 靜態註冊接收失效 | 清單文件聲明 `android:exported="true"` 或改用顯式 Intent/LocalBroadcast |
自定義 View 發送廣播完全可行,核心是在構造方法獲取並持有 Activity Context,配合 `LocalBroadcastManager` 或接口回調,可實現高性能、低耦合的實時數據通信。切記生命周期管理,防洩漏、防崩潰。