【问题标题】:Are Android's BroadcastReceivers started in a new thread?Android 的 BroadcastReceivers 是否在新线程中启动?
【发布时间】:2011-07-20 16:17:33
【问题描述】:

如果我有一个在我的Service 类中扩展BroadcastReceiver 的内部类,当BroadcastReceiver 类从Service 类读取/写入对象时,我是否应该关心同步? 或者换一种说法:BroadacstReceiveronReceive() 方法是在额外的线程中启动的吗?

【问题讨论】:

    标签: android multithreading concurrency broadcastreceiver


    【解决方案1】:

    onReceive() 方法始终在主线程(也称为“UI 线程”)上调用,除非您使用 registerReceiver() 变体请求将其安排在不同的线程上:

    Context.registerReceiver(BroadcastReceiver receiver,
                             IntentFilter filter,
                             String broadcastPermission,
                             Handler scheduler)
    

    【讨论】:

    • LocalBroadcastManager 呢?为什么没有这种方法?
    【解决方案2】:

    Android 的 BroadcastReceivers 是否在新线程中启动?

    通常但并非总是如此,这完全取决于您如何注册。

    如果您使用以下方式注册 BroadcastReceiver

    registerReceiver(BroadcastReceiver receiver, IntentFilter filter)
    

    它将在主活动线程(又名 UI 线程)中运行。

    如果您使用在不同线程上运行的有效Handler 注册您的BroadcastReceiver

    registerReceiver (BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)
    

    它将在您的 Handler

    的上下文中运行

    例如:

    HandlerThread handlerThread = new HandlerThread("ht");
    handlerThread.start();
    Looper looper = handlerThread.getLooper();
    Handler handler = new Handler(looper);
    context.registerReceiver(receiver, filter, null, handler); // Will not run on main thread
    

    详情here & here

    【讨论】:

    • 蚕儿。那么onReceive中的Toast.makeText(..data)操作是线程安全的吗?
    【解决方案3】:

    The onReceive() method is called on the main thread. 因此,如果您对服务类的所有访问都是在主线程中完成的,那么您不需要任何同步。

    【讨论】:

    • 所以他的问题的答案是否定的! onReceive 方法不在额外的线程上运行。
    • Android Cookbook:请注意,BroadcastReceiver 运行在意图广播的同一线程上;在我们的示例中,这是主/GUI 线程!
    • @Stephan,所以 Toast.makeText(..data)onReceive 中的操作,其中 data 是从服务中的后台线程传递的线程安全吗?
    【解决方案4】:

    如果您使用 Android 广播接收器,默认情况下会在 GUI 线程(主线程)中启动 RegisterReceiver(broadcastReceiver, intentFilter).

    但它可以在工作线程中运行,如下所示;

    使用HandlerThread时,一定要注销BroadcastReceiver后退出线程。如果没有,文件描述符(FD)泄漏发生在Linux级别,如果继续注册/取消注册,最终应用程序会崩溃。

    unregisterReceiver(...);

    然后 looper.quit(); 要么 looper.quitSafely();

    private Handler broadcastReceiverHandler = null;
    private HandlerThread broadcastReceiverThread = null;
    private Looper broadcastReceiverThreadLooper = null;
    
    private BroadcastReceiver broadcastReceiverReadScans = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
    
        }
    }
    
    private void registerForIntents() {
        broadcastReceiverThread = new HandlerThread("THREAD_NAME");//Create a thread for BroadcastReceiver
        broadcastReceiverThread.start();
    
        broadcastReceiverThreadLooper = broadcastReceiverThread.getLooper();
        broadcastReceiverHandler = new Handler(broadcastReceiverThreadLooper);
    
        IntentFilter filterScanReads = new IntentFilter();
        filterScanReads.addAction("ACTION_SCAN_READ");
        filterScanReads.addCategory("CATEGORY_SCAN");
    
        context.registerReceiver(broadcastReceiverReadScans, filterScanReads, null, broadcastReceiverHandler);
    }
    
    private void unregisterIntents() {
        context.unregisterReceiver(broadcastReceiverReadScans);
        broadcastReceiverThreadLooper.quit();//Don't forget
    }
    

    【讨论】:

      【解决方案5】:

      此外,您可以在 AndroidManifest.xml 中指定“android:process”接收器元素属性。见here。这样,您可以指定接收器作为单独的进程运行,并且不绑定到主 UI 线程。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-03-19
        • 1970-01-01
        • 2011-09-03
        • 2012-02-28
        • 1970-01-01
        • 1970-01-01
        • 2015-11-21
        相关资源
        最近更新 更多