Application.ActivityLifecycleCallbacksでActivityを監視する

&autolink(id=main)

目次


参考にするリンク

Application.ActivityLifecycleCallbacks
http://developer.android.com/reference/android/app/Application.ActivityLifecycleCallbacks.html

ActivityLifecycleCallbacksを使う。

API-14 で ActivityのLifecycleを通知してくれる仕組みが公式に入った。
ActivityLifecycleCallbacks
これを使ってActivityのスタックを監視してみる。

ActivityLifecycleCallbacksを登録する。

使い方は、
  • ActivityLifecycleCallbacksを実装したクラスを
  • Application#registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks)で登録
するだけ。

  1. public class TestApplication extends Application implements ActivityLifecycleCallbacks {
  2. @Override
  3. public void onCreate() {
  4. super.onCreate();
  5.  
  6. registerActivityLifecycleCallbacks(this);
  7. }
  8.  
  9. // ================================================================
  10. // ActivityLifecycleCallbacksのメソッド郡
  11. public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
  12. }
  13.  
  14. public void onActivityPaused(Activity activity) {
  15. }
  16.  
  17. public void onActivityDestroyed(Activity activity) {
  18. }
  19.  
  20. public void onActivityStarted(Activity activity) {
  21. }
  22.  
  23. public void onActivityResumed(Activity activity) {
  24. }
  25.  
  26. public void onActivityStopped(Activity activity) {
  27. }
  28.  
  29. public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
  30. }
  31. }

ActivityLifecycleCallbacksで監視する。

基本的にActivityLifecycleCallbacksは、
各Activityの処理よりも先行して処理を書くのではなくて
後々利いてくる処理を書いておいたり、
スタックを気にする処理を書いておくのがいいと思う。

ただ、これはあくまでLifecycleを拾えるだけで、必ずしも予想通りに動作するとは限らない。

フレームワークに手を入れられている場合はLifecycle無視で処理されることもあり、
信じてもよさそうなのは onCreate と onPause だけ。
あとは Intent.FLAG_ACTIVITY_CLEAR_TOP で唯一動作する onDestroy で
onPause で書いた終了処理と同じ構成を作っておくくらいか。。。

ActivityLifecycleCallbacksを眺める。

さて、ActivityLifecycleCallbacksのコールバックメソッド郡は、
名前の通り 各対応メソッドが呼ばれた後に コールバックされる。
onActivityCreated なら onCreate の後にコールバック
といった具合。
ただこのタイミングが、通常は実処理より早い。

ActivityLifecycleCallbacksのコールバック処理は、
Applicationのソースにコールバックを行う処理が入っている。
  • dispatchActivityCreated(Activity, Bundle)
  • dispatchActivityStarted(Activity)
  • dispatchActivityResumed(Activity)
  • dispatchActivityPaused(Activity)
  • dispatchActivityStopped(Activity)
  • dispatchActivitySaveInstanceState(Activity, Bundle)
  • dispatchActivityDestroyed(Activity)

で、このコールバックがいつ呼ばれるのかというと、Activity#onCreate()などである。

  1. public class Activity extends ContextThemeWrapper
  2. implements LayoutInflater.Factory2,
  3. Window.Callback, KeyEvent.Callback,
  4. OnCreateContextMenuListener, ComponentCallbacks2 {
  5.  
  6. protected void onCreate(Bundle savedInstanceState) {
  7. if (mLastNonConfigurationInstances != null) {
  8. mAllLoaderManagers = mLastNonConfigurationInstances.loaders;
  9. }
  10. if (savedInstanceState != null) {
  11. Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
  12. mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
  13. ? mLastNonConfigurationInstances.fragments : null);
  14. }
  15. mFragments.dispatchCreate();
  16. getApplication().dispatchActivityCreated(this, savedInstanceState);
  17. mCalled = true;
  18. }
  19. }

つまり、普段書くような以下のようなActivityの場合は、
  • super.onCreate(savedInstanceState);
  • dispatchActivityCreated(Activity, Bundle)
が動作してから処理部にくる。

  1. public class HomeActivity extends Activity {
  2.  
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6.  
  7. // 何らかの処理
  8. }
  9. }

なお、元々処理があんまり入ってない onPause や onStop はいいとして、
onDestroy も同様に最後にコールバックされるので注意。

  1. protected void onDestroy() {
  2. mCalled = true;
  3.  
  4. // dismiss any dialogs we are managing.
  5. if (mManagedDialogs != null) {
  6. final int numDialogs = mManagedDialogs.size();
  7. for (int i = 0; i < numDialogs; i++) {
  8. final ManagedDialog md = mManagedDialogs.valueAt(i);
  9. if (md.mDialog.isShowing()) {
  10. md.mDialog.dismiss();
  11. }
  12. }
  13. mManagedDialogs = null;
  14. }
  15.  
  16. // close any cursors we are managing.
  17. synchronized (mManagedCursors) {
  18. int numCursors = mManagedCursors.size();
  19. for (int i = 0; i < numCursors; i++) {
  20. ManagedCursor c = mManagedCursors.get(i);
  21. if (c != null) {
  22. c.mCursor.close();
  23. }
  24. }
  25. mManagedCursors.clear();
  26. }
  27.  
  28. // Close any open search dialog
  29. if (mSearchManager != null) {
  30. mSearchManager.stopSearch();
  31. }
  32.  
  33. getApplication().dispatchActivityDestroyed(this);
  34. }
  35.  

onPause は特にANRのタイムアウトがあるので、
どちらにしたところで重い処理はやらない方がいい。
この辺が監視処理だけに留めた方がよい理由でもある。

まとめ

Application.registerActivityLifecycleCallbacks() で
ActivityLifecycleCallbacks を実装したクラスを登録すると、
各種Activityのコールバックを受けられる。

ただし、Activity#onCreate()などの処理の中で呼ばれるので、
  • 実処理よりも早い段階でコールバックが呼ばれたり、
  • 重い処理を行うとANRが発生したり、
する。
全体のスタック監視や、どうしても管理が必要な場合のみに
使用を留めるべき。

関連リンク

&trackback()


  • zzz - yy 2015-01-15 14:36:00


最終更新:2012年02月12日 20:26