2010年11月8日月曜日

BroadcastReceiver を別プロセスで動かしてみたときの感想文

BroadcastReceiver を別プロセスで動かしたところ、
ただの知識不足が原因と言えるのですが、
一部、予想外の動きだったので、その驚き?をメモしておきます。

別プロセスで動かすということで、
マニフェスト・ファイルには、以下のように記述しました。

AndroidManifest.xml
<receiver android:name=".LocationReceiver" android:process=":remote"/>

LocationReceiver が BroadcastReceiver を拡張したクラスになります。


LocationReceiver には以下のような記述をしました。

LocationReceiver.java
public class LocationReceiver extends BroadcastReceiver {

  LocationManager mLocationMgr;
  
  public void onReceive(Context arg0, Intent arg1) {

    if (mLocationMgr == null) {
      mLocationMgr = (LocationManager) arg0
        .getSystemService(arg0.LOCATION_SERVICE);
    }
  }
  
}

で、ここから意外だったんですが、
毎回毎回 mLocationMgr が null になることが分かりました。

2回目以降の呼び出しでは、null 以外を想定していました。


なんでじゃい!と思って、調べてみると、

まず、BroadcastReceiver は onReceive() を実行している間のみ Active で、
実行が終われば、Inactive になると記述があります。

Broadcast receiver lifecycle からの抜粋。
When a broadcast message arrives for the receiver, Android calls its onReceive() method and passes it the Intent object containing the message. The broadcast receiver is considered to be active only while it is executing this method. When onReceive() returns, it is inactive.

さらに同ページのプロセスのライフ・サイクルの記述を見ると、
Empty process という存在の記述があります。

Processes and lifecycles
  1. An empty process is one that doesn't hold any active application components. The only reason to keep such a process around is as a cache to improve startup time the next time a component needs to run in it. The system often kills these processes in order to balance overall system resources between process caches and the underlying kernel caches.

DDMS で見ると、":remote" がプロセス名に付与されたプロセスが同一の PID で存在し続けるので、
onReceive() 実行後も empty process として残っていると考えられます。

以上の2点を踏まえて、今回の動きを説明すると、
どうも以下のような動きをしているようです。
  1. プロセス生成。
  2. LocationReceiver 初期化、onReceiver() 実行。
  3. onReceiver() 終了後、LocationReceiver を破棄。
  4. プロセスは残る。

で、2回目以降の呼び出しでは、2. から実行される、と思われます。

ふ~ん、、、って感じですね。。
( ̄ー ̄;アセアセ