android - LocalBroadcastManager 和 Activity 生命周期

标签 android android-lifecycle localbroadcastmanager

所以我正在研究将一些长时间运行的网络操作从回调接口(interface)更改为本地广播的可行性。由于 Activity 生命周期会为需要修改 UI 的异步请求创建各种复杂情况(断开 Activity 与 onDestroy() 中的回调的连接,不要修改 FragmentTransactiononSaveInstanceState() 等之后),我认为使用本地广播更有意义,我们可以在生命周期事件中注册/注销接收器。

但是,当 Activity 在配置更改期间被销毁并重新创建时,广播接收器将不会注册的时间很短(例如在 onPause()/onResume() 之间) ).因此,例如,如果 savedInstanceState == null(例如,对于 Activity 的首次启动),我们在 onCreate() 中启动异步请求,isn'如果用户在操作完成之前改变他们的设备方向,完成后发送的广播是否有可能丢失?(即接收器在 onPause() 上取消注册,然后操作完成,然后接收器重新-注册在onResume())

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

最佳答案

onRetainNonConfigurationInstance() 中所述Activity的方法,当Activity正在重启的过程中,系统会关闭主线程中的消息队列处理。这确保发布到主线程的事件将始终在 Activity 生命周期的稳定点交付。

但是,LocalBroadcastManagersendBroadcast() 方法似乎存在设计缺陷,因为它评估注册的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/

相关文章:

java - 如何从 Object 类的数组中提取游标和整数值?

android - 如何使用 ParseQueryAdapter (Android + Parse) 从另一个类获取数据

机器人: fragment 的 Recyclerview?

java - 使用 viewModels 从 ChildFragment 访问 ParentFragment 中的 ViewModel

android - 在游戏结束时存储数据 Unity

android - 通过执行单个任务命令为所有模块运行 Ktlint

android - Dagger 2 注入(inject) ViewModel 异常行为(ViewModel 未在屏幕旋转时重新使用)

android - LocalBroadcastManager 未在 Activity 中接收广播

android - 在 manifest.xml 中声明的 BroadcatReceiver 未接收到 LocalBroadcastManager Intent

android - 带小部件的 LocalBroadcastManager