2016-07-13 7 views
2

私はObservableのBluetooth状態を監視するこの小さなutilメソッドを持っています。アクティビティが破棄されたときにサブスクリプション外のBroadcastReceiverの登録を解除する

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)); 
    }) 
} 

私のアクティビティでこのメソッドを使用すると、ユーザーがいつBluetoothを有効にしたかが分かります。これは正常に動作しますが、アクティビティが突然終了するとリークします。

onDestroyで登録を解除できますが、BroadcastReceiverの登録を解除するにはどうすればよいですか?

アイデア?

+0

あなたが作成した観察可能なものはバックプレッシャをサポートしていないので、ダウンストリーム演算子から 'MissingBackpressureException'がトリガされるのを避けるためには、 '.onBackpressureXXX()'でtを指定します。 –

答えて

4

getBluetoothStateObservableがどのように設定されているかを考えると、サブスクライバがサブスクライブしないと、BroadcastReceiverは登録解除されます。唯一のやり方は、Android Activityライフサイクルが開始されたときに、実際には購読を解除することです。

この場合、Subscriptionインスタンスを保持することも、CompositeSubscriptionを使用することもできます。

のonCreateまたはONSTARTで

(例えば):onDestroyまたはonStopで

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

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

いつものように、ダンルーはhttp://blog.danlew.net/2014/10/08/grokking-rxjava-part-4/(RxJavaで動作する方法のAndroidライフサイクルの偉大な説明を持っています)

+0

もちろん、ああ。私は思ったよりも簡単です。ありがとう! – Vas

2

正直なところ、私はバックグラウンド(または殺した)のアクティビティを(たとえ可能であっても)うまく実行しているとは思わない。 DOCSによると

活動は、ユーザーが行うことができ、単一、集中ものです。ほとんどすべてのアクティビティがユーザとやり取りするので、ActivityクラスはsetContentView(View)でUIを配置できるウィンドウを作成します。アクティビティはフルスクリーンウィンドウとしてユーザーに表示されることがありますが、フローティングウィンドウ...またはアクティビティグループを使用して別のアクティビティ内に埋め込まれるなど、他の方法でも使用できます。

アクティビティがバックグラウンドの場合、表示されません。したがって、(ユーザーには表示されないため)内容を更新することは無意味です。あなたが活動のビューを更新する必要がある場合には、アプリが開いている場合にのみ、それを行うことは理にかなって、

  • は実際には、次のようなさまざまなアプローチを検討すべきです。だから、アプリが殺された場合(またはバックグラウンドで)、それを更新することは無意味です(ユーザーはとにかくそれを見ていません)。

  • Bluetoothイベントが発生したときに1つのアクションを実行する必要がある場合は、BroadcastReceiverで直接実行してください。

  • 長いタスクを実行する必要がある場合は、サービスを作成します。このようにして、BroadcastReceiverは、期待しているイベントを受信した後にサービスを開始(および "話す")ことができます。

  • BroadcastReceiverを使用して、後で使用できるように情報を保存します。

    • の場合:この方法では、覚えておいてください、ユーザーもう一度あなたのアプリを開くと、アクティビティ、あなたが保存して情報を相談することができonCreate()onResult()中に(それに応じてビューを準備する方法

    。あなたが活動を必要とする、UI要素を表示する必要があります。

  • あなたがイベントについて通知する必要がある場合は、BroadcastReceiverを必要としています。

  • バックグラウンドでいくつかのタスクを実行し続ける必要がある場合は、サービスが必要です。

関連する問題