所以我正在研究将一些长时间运行的网络操作从回调接口(interface)更改为本地广播的可行性。由于 Activity 生命周期会为需要修改 UI 的异步请求创建各种复杂情况(断开 Activity 与 onDestroy()
中的回调的连接,不要修改 FragmentTransaction
在 onSaveInstanceState()
等之后),我认为使用本地广播更有意义,我们可以在生命周期事件中注册/注销接收器。
但是,当 Activity 在配置更改期间被销毁并重新创建时,广播接收器将不会注册的时间很短(例如在 onPause()/onResume()
之间) ).因此,例如,如果 savedInstanceState == null
(例如,对于 Activity 的首次启动),我们在 onCreate()
中启动异步请求,isn'如果用户在操作完成之前改变他们的设备方向,完成后发送的广播是否有可能丢失?(即接收器在 onPause() 上取消注册,然后操作完成,然后接收器重新-注册在onResume())
如果是这种情况,那么它会增加很多额外的复杂性,我们需要为其添加支持,而且它可能不值得转换。我研究了其他东西,例如 Otto EventBus 库,但我不确定它是否有同样的问题需要担心。
最佳答案
如 onRetainNonConfigurationInstance()
中所述Activity
的方法,当Activity
正在重启的过程中,系统会关闭主线程中的消息队列处理。这确保发布到主线程的事件将始终在 Activity
生命周期的稳定点交付。
但是,LocalBroadcastManager
的sendBroadcast()
方法似乎存在设计缺陷,因为它评估注册的BroadcastReceiver
从发布线程 before 排队要在主线程上传送的广播,而不是在广播传送时在主线程上评估它们。虽然这使它能够报告传送成功或失败,但它没有提供适当的语义来允许 BroadcastReceiver
从主线程安全地临时注销而不可能丢失潜在的广播。
解决方案是使用 Handler
从主线程发布广播,使用 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));
}
}
}
关于android - LocalBroadcastManager 和 Activity 生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22052195/