LocalBroadcastManager和Activity生命周期

kco*_*ock 5 android android-lifecycle localbroadcastmanager

因此,我正在研究从一些长期运行的网络操作中将回调接口更改为本地广播的可行性.由于Activity生命周期为需要修改UI的异步请求创建了各种复杂功能(将Activity与回调断开连接onDestroy(),不要FragmentTransaction在之后修改s onSaveInstanceState()等),我认为使用本地广播更有意义,我们可以在生命周期事件中注册/取消注册接收器.

但是,当在配置更改期间销毁并重新创建活动时,没有注册广播接收器(onPause()/onResume()例如)之间的这个小窗口时间.因此,例如,如果我们在onCreate()if中启动异步请求savedInstanceState == null(例如,对于活动的第一次启动),如果用户在操作完成之前更改其设备方向,则完成时发送的广播是否可能丢失?(即接收器在onPause()上未注册,然后操作完成,然后接收器在onResume()中重新注册)

如果是这种情况,那么它会增加我们需要添加支持的额外复杂性,而且可能不值得切换.我已经研究了其他东西,比如Otto EventBus库,但我不确定它是否有同样的问题需要担心.

cor*_*992 3

正如onRetainNonConfigurationInstance()的方法中所述Activity,系统在Activity重新启动过程中禁用主线程中的消息队列处理。这确保了发布到主线程的事件将始终在Activity.

sendBroadcast()然而,的方法似乎存在一个设计缺陷LocalBroadcastManager,因为它在将广播排队到主线程上传递之前BroadcastReceiver评估发布线程中注册的 s ,而不是在广播时在主线程上评估它们送货。虽然这使它能够报告传递的成功或失败,但它没有提供正确的语义来允许s 暂时从主线程安全地取消注册,而不会丢失潜在的广播。BroadcastReceiver

解决方案是使用 aHandler从主线程发布广播,使用该sendBroadcastSync()方法,以便立即传递广播而不是重新发布。这是实现此功能的示例实用程序类:

public class LocalBroadcastUtils extends Handler {
    private final LocalBroadcastManager manager;

    private LocalBroadcastUtils(Context context) {
        super(context.getMainLooper());
        manager = LocalBroadcastManager.getInstance(context);
    }

    @Override
    public void handleMessage(Message msg) {
        manager.sendBroadcastSync((Intent) msg.obj);
    }

    private static LocalBroadcastUtils instance;

    public static void sendBroadcast(Context context, Intent intent) {
        if (Looper.myLooper() == context.getMainLooper()) {
            // If this is called from the main thread, we can retain the
            // "optimization" provided by the LocalBroadcastManager semantics.
            // Or we could just revert to evaluating matching BroadcastReceivers
            // at the time of delivery consistently for all cases.
            LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
        } else {
            synchronized (LocalBroadcastUtils.class) {
                if (instance == null) {
                    instance = new LocalBroadcastUtils(context);
                }
            }
            instance.sendMessage(instance.obtainMessage(0, intent));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)