Android 当活动被销毁时,在订阅外部注销BroadcastReceiver

Android 当活动被销毁时,在订阅外部注销BroadcastReceiver,android,bluetooth,broadcastreceiver,rx-java,rx-android,Android,Bluetooth,Broadcastreceiver,Rx Java,Rx Android,我有一个小的util方法,它让我可以观察到蓝牙状态 public static Observable<Integer> getBluetoothStateObservable(Context context) { final Context appContext = context.getApplicationContext(); return Observable.create(observer -> { final Broadcast

我有一个小的util方法,它让我可以观察到蓝牙状态

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));
    })
}
公共静态可观察getBluetoothStateObservable(上下文){
final Context appContext=Context.getApplicationContext();
返回可观察的。创建(观察者->{
final BroadcastReceiver BroadcastReceiver=新的BroadcastReceiver(){
@凌驾
公共void onReceive(上下文、意图){
int btState=intent.getIntExtra(BluetoothAdapter.EXTRA\u状态,BluetoothAdapter.STATE\u关闭);
交换机(btState){
案例BluetoothAdapter.ERROR:
observer.onError(新的IllegalArgumentException(“更改蓝牙状态时出错”);
打破
机箱BluetoothAdapter.STATE\u关闭:
机箱BluetoothAdapter.STATE_打开:
observer.onCompleted();
打破
违约:
onNext观察员(btState);
打破
}
}
};
add(Subscriptions.create(()->appContext.unregisterReceiver(broadcastReceiver));
registerReceiver(broadcastReceiver,新的IntentFilter(BluetoothAdapter.ACTION\u STATE\u CHANGED));
})
}
当我在活动中使用此方法时,我知道用户何时启用了蓝牙。这工作正常,但当活动突然停止时,它会泄漏

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


有什么想法吗?

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

根据:

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

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

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

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

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

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

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

记住:

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

  • 如果需要获得事件通知,则需要广播接收器

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


给定getBluetoothStateObservable的设置方式,当订阅者取消订阅时,BroadcastReceiver将被取消注册。唯一的技巧是确保它确实在Android活动生命周期开始时被取消订阅

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

在onCreate或onStart中(例如):

在onDestroy或onStop中:

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

与往常一样,Dan Lew对Android生命周期应该如何与RxJava()一起工作有很好的解释。

您创建的observable不支持背压,因此为了避免触发下游运营商的
MissingBackpressureException
,您应该将其与
.onBackpressurexx()
结合使用。
mSubscription.unsubscribe();
or
mCompositeSubscription.clear();