我有一个小的实用方法,可以让我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 元素,则需要一个活动。
-
如果您需要收到有关事件的通知,则需要一个广播接收器。
-
如果您需要在后台继续运行某些任务,则需要一个服务。