当活动被销毁时,在订阅之外取消注册广播接收器



我有一个小的实用方法,可以让我Observable监控蓝牙状态。

public static Observable<Integer> getBluetoothStateObservable(Context context) {
    final Context appContext = context.getApplicationContext();
    return Observable.create(observer -> {
            final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
                    switch (btState) {
                        case BluetoothAdapter.ERROR:
                            observer.onError(new IllegalArgumentException("Error occurred while changing bluetooth state"));
                            break;
                        case BluetoothAdapter.STATE_OFF:
                        case BluetoothAdapter.STATE_ON:
                            observer.onCompleted();
                            break;
                        default:
                            observer.onNext(btState);
                            break;
                    }
                }
            };
            observer.add(Subscriptions.create(() -> appContext.unregisterReceiver(broadcastReceiver)));
            appContext.registerReceiver(broadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
    })
}

当我在活动中使用此方法时,我知道用户何时启用了蓝牙。这工作正常,但是当活动突然被杀死时,它会泄漏。

我可以在onDestroy中取消订阅,但如何取消注册BroadcastReceiver

有什么想法吗?

鉴于getBluetoothStateObservable的设置方式,当订阅者取消订阅时,BroadcastReceiver将被取消注册。唯一的技巧是确保它确实在Android活动生命周期发挥作用时被取消订阅。

在这种情况下,您可以保留订阅实例,也可以使用 CompositeSubscription。

在 onCreate 或 onStart 中(例如):

mSubscription = getBluetoothStateObservable(this).subscribe();
or 
mCompositeSubscription.add(getBluetoothStateObservable(this).subscribe());

在 onDestroy 或 onStop 中:

mSubscription.unsubscribe();
or
mCompositeSubscription.clear();

往常一样,Dan Lew对Android生命周期应该如何与RxJava一起工作进行了很好的解释(http://blog.danlew.net/2014/10/08/grokking-rxjava-part-4/)。

老实说,我不认为更新后台(或被杀)的活动是一种好的做法(即使可能)。

根据 DOCS:

活动

是用户可以执行的单个、专注的事情。几乎所有活动都与用户交互,因此 Activity 类负责为您创建一个窗口,您可以在其中使用 setContentView(View) 放置 UI。虽然活动通常以全屏窗口的形式呈现给用户,但它们也可以以其他方式使用:作为浮动窗口...或嵌入到另一个活动中(使用活动组)。

因此,如果活动在后台,则不可见。因此,更新其内容是没有用的(因为它对用户不可见)。

事实上,您应该考虑不同的方法,例如:

  • 如果需要更新活动中的视图,则仅在应用打开时才执行此操作是有意义的。因此,如果应用程序被杀死(或在后台),则更新它是没有用的(无论如何用户都看不到它)。

  • 如果您需要在蓝牙事件发生时执行单个操作,请直接在 BroadcastReceiver .

  • 如果需要运行长任务,请创建服务。这样,您的BroadcastReceiver可以在收到您期望的事件后启动(并与之"交谈")服务。

  • 使用您的广播接收器存储信息以供以后使用。这样,当用户再次打开您的应用时,您的活动可以查阅您保存的信息,然后相应地准备视图(在onCreate()onResult()方法期间。

记得:

  • 如果需要显示 UI 元素,则需要一个活动。

  • 如果您需要收到有关事件的通知,则需要一个广播接收器。

  • 如果您需要在后台继续运行某些任务,则需要一个服务。

相关内容

  • 没有找到相关文章

最新更新