首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 開發:動態註冊內部類作為 BroadcastReceiver 的正確姿勢

     編輯:程式設計綜合問答

問題背景

在 Android 中,除了在 Manifest 中靜態聲明 <receiver>,更常見的是在代碼中動態註冊廣播接收器。當接收器實現為外部類的內部類(非靜態)時,註冊方式稍有不同,需注意持有外部類引用的生命週期問題。

正確註冊代碼

public class MainActivity extends AppCompatActivity {
    // 1. 定義內部類接收器(非 static,可訪問外部類成員)
    public class MyBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // 處理廣播邏輯,可直接訪問 MainActivity 成員
            String action = intent.getAction();
            if ("com.example.CUSTOM_ACTION".equals(action)) {
                String data = intent.getStringExtra("key");
                updateUI(data); // 直接調用外部類方法
            }
        }
    }
    
    private MyBroadcastReceiver mReceiver;
    private IntentFilter mFilter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 2. 實例化內部類接收器
        mReceiver = new MyBroadcastReceiver();
        
        // 3. 創建 IntentFilter 指定監聽的 Action
        mFilter = new IntentFilter("com.example.CUSTOM_ACTION");
        // 可添加多個 Action
        mFilter.addAction("com.example.ANOTHER_ACTION");
        
        // 4. 動態註冊
        registerReceiver(mReceiver, mFilter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 5. 關鍵:反註冊防止內存洩漏和崩潰
        if (mReceiver != null) {
            unregisterReceiver(mReceiver);
            mReceiver = null;
        }
    }
}

關鍵注意事項

  • 非靜態內部類持有外部引用:內部類實例隱式持有 MainActivity.this 引用,若 Activity 銷毀未反註冊,會導致內存洩漏,甚至因接收廣播操作已銷毀視圖而崩潰。
  • 生命週期匹配:建議在 onCreate() 註冊,onDestroy() 反註冊;或 onResume()/onPause() 配對,視業務需求而定。
  • 靜態內部類替代方案:若接收器邏輯不依賴外部類狀態,建議改為 static class MyReceiver extends BroadcastReceiver 並通過 WeakReference<Activity> 持有弱引用,更安全。
  • Android 8.0+ 限制:隱式廣播(無指定包名)多數不能動態註冊接收,需使用顯式 Intent 或 JobScheduler/WorkManager 替代。
  • 導出屬性:動態註冊的接收器默認 android:exported="true",若涉及敏感操作需在 onReceive 中驗證權限或簽名。

發送廣播示例

// 發送有序廣播(可被攔截)
Intent intent = new Intent("com.example.CUSTOM_ACTION");
intent.putExtra("key", "測試數據");
sendOrderedBroadcast(intent, null);

// 發送普通廣播
sendBroadcast(intent);

// 本地廣播(進程內,更安全高效)
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved