2012年2月5日日曜日

AsyncTaskLoader使ってみた…んだけど

今更ながらAsyncTaskLoaderを使って見ました。

コンパチライブラリを使用してです。(未だに2系だけしか持ってません( ー`дー´)キリッ)
動作させたのは2.2のエミュレータとDesire(2.2)とINFOBAR(2.3)

以下参考サイト
時代はAsyncTaskよりAsyncTaskLoader
ソフトウェア技術ドキュメントを勝手に日本語化

サンプルはこちら
githubじゃなくてスミマセン。
単に指定した秒数待ってランダムに値をぶん投げるだけのものですが…
https://bitbucket.org/daneko/asynctaskloadercheck

まあ今までAsyncTaskは使わずに自前でThread書いたりHandlerに投げたりばっかしてました…
なのでこれからは時代の流れにそってAsyncTaskLoaderを使いたいと思います。



で終わるんだったらこのエントリーはしません。

以下ハマった現象

画面回転を行なうと「FragmentActivityから生成されたLoader側はなぜかおかしい挙動をする
Fragment#getLoaderManagerで生成したものは期待通りの動きをするんですが…

何を言っているのかわか(ry

とりあえずおもむろにログを晒す

02-05 18:36:30.732: D/jp.omokageru.dnk.loader.HelloLoaderActivity(613): onButtonClick
02-05 18:36:30.732: V/LoaderManager(613): initLoader in LoaderManager{44f79998 in HelloLoaderActivity{44f43928}}: args=Bundle[{sleeptime=2000}]
02-05 18:36:30.741: D/jp.omokageru.dnk.loader.HelloLoaderActivity(613): onCreateLoader
02-05 18:36:30.741: D/jp.omokageru.dnk.loader.CheckLoader(613): CheckLoader
02-05 18:36:30.741: V/LoaderManager(613):   Starting: LoaderInfo{44f7adb0 #0 : CheckLoader{44f7af20}}
02-05 18:36:30.741: D/jp.omokageru.dnk.loader.CheckLoader(613): onStartLoading
02-05 18:36:30.771: V/LoaderManager(613):   Created new loader LoaderInfo{44f7adb0 #0 : CheckLoader{44f7af20}}
02-05 18:36:30.781: D/jp.omokageru.dnk.loader.CheckLoader(613): loadInBackground
02-05 18:36:32.786: V/LoaderManager(613): onLoadComplete: LoaderInfo{44f7adb0 #0 : CheckLoader{44f7af20}}
02-05 18:36:32.786: V/LoaderManager(613):   onLoadFinished in CheckLoader{44f7af20 id=0}: String{44f7e390}
02-05 18:36:32.791: D/jp.omokageru.dnk.loader.HelloLoaderActivity(613): onLoadFinished
02-05 18:36:32.791: D/jp.omokageru.dnk.loader.HelloLoaderActivity(613): loader:CheckLoader{44f7af20 id=0}
02-05 18:36:32.791: D/jp.omokageru.dnk.loader.HelloLoaderActivity(613): data:Finish9
02-05 18:36:42.191: V/LoaderManager(613): Retaining in LoaderManager{44f79998 in HelloLoaderActivity{44f43928}}
02-05 18:36:42.191: V/LoaderManager(613):   Retaining: LoaderInfo{44f7adb0 #0 : CheckLoader{44f7af20}}
02-05 18:36:42.191: V/LoaderManager(613): Destroying Inactive in LoaderManager{44f79998 in HelloLoaderActivity{44f43928}}
02-05 18:36:42.291: V/LoaderManager(613): Finished Retaining in LoaderManager{44f79998 in HelloLoaderActivity{44f813a0}}
02-05 18:36:42.331: V/LoaderManager(613):   Finished Retaining: LoaderInfo{44f7adb0 #0 : CheckLoader{44f7af20}}
02-05 18:36:42.331: V/LoaderManager(613):   Stopping: LoaderInfo{44f7adb0 #0 : CheckLoader{44f7af20}}
02-05 18:36:46.451: D/jp.omokageru.dnk.loader.HelloLoaderActivity(613): onButtonClick
02-05 18:36:46.451: V/LoaderManager(613): restartLoader in LoaderManager{44f79998 in HelloLoaderActivity{44f813a0}}: args=Bundle[{sleeptime=2000}]
02-05 18:36:46.451: V/LoaderManager(613):   Making last loader inactive: LoaderInfo{44f7adb0 #0 : CheckLoader{44f7af20}}
02-05 18:36:46.451: D/jp.omokageru.dnk.loader.HelloLoaderActivity(613): onCreateLoader
02-05 18:36:46.451: D/jp.omokageru.dnk.loader.CheckLoader(613): CheckLoader
02-05 18:36:51.482: V/LoaderManager(613): Retaining in LoaderManager{44f79998 in HelloLoaderActivity{44f813a0}}
02-05 18:36:51.491: W/LoaderManager(613): Called doRetain when not started: LoaderManager{44f79998 in HelloLoaderActivity{44f813a0}}
02-05 18:36:51.491: W/LoaderManager(613): java.lang.RuntimeException: here
02-05 18:36:51.491: W/LoaderManager(613):  at android.support.v4.app.LoaderManagerImpl.doRetain(LoaderManager.java:733)
02-05 18:36:51.491: W/LoaderManager(613):  at android.support.v4.app.FragmentActivity.onReallyStop(FragmentActivity.java:634)
02-05 18:36:51.491: W/LoaderManager(613):  at android.support.v4.app.FragmentActivity.doReallyStop(FragmentActivity.java:616)
02-05 18:36:51.491: W/LoaderManager(613):  at android.support.v4.app.FragmentActivity.onRetainNonConfigurationInstance(FragmentActivity.java:442)
02-05 18:36:51.491: W/LoaderManager(613):  at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3617)
02-05 18:36:51.491: W/LoaderManager(613):  at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3673)
02-05 18:36:51.491: W/LoaderManager(613):  at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3789)
02-05 18:36:51.491: W/LoaderManager(613):  at android.app.ActivityThread.access$2400(ActivityThread.java:125)
02-05 18:36:51.491: W/LoaderManager(613):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2037)
02-05 18:36:51.491: W/LoaderManager(613):  at android.os.Handler.dispatchMessage(Handler.java:99)
02-05 18:36:51.491: W/LoaderManager(613):  at android.os.Looper.loop(Looper.java:123)
02-05 18:36:51.491: W/LoaderManager(613):  at android.app.ActivityThread.main(ActivityThread.java:4627)
02-05 18:36:51.491: W/LoaderManager(613):  at java.lang.reflect.Method.invokeNative(Native Method)
02-05 18:36:51.491: W/LoaderManager(613):  at java.lang.reflect.Method.invoke(Method.java:521)
02-05 18:36:51.491: W/LoaderManager(613):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
02-05 18:36:51.491: W/LoaderManager(613):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
02-05 18:36:51.491: W/LoaderManager(613):  at dalvik.system.NativeStart.main(Native Method)

ログを見たら破棄したローダを再利用して落ちているように見えます。

発生させる挙動としては以下
  • アプリを立ち上げる
  • AsyncTaskLoaderを実行する
  • 結果を見る
  • 画面回転する
  • AsyncTaskLoaderを実行する
  • onCreateLoaderで止まる(なぜ…)
  • 再度画面回転する
  • 上記ログが出る

回避方法はわかった範囲では以下2つ
  • 画面回転時Activityを破棄しないようにする(単に逃げる)
  • onCreate時にFragmentActivity#getSupportLoaderManagerを呼び出す(なぜうまく行くのかわからん…)
2つ目なんてバットノウハウ以外の何者でもないんだけど

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // ここでの呼び出しを無くすとなぜか画面回転後は動作しなくなる
        // しかもonCreate以外での呼び出しは駄目っぽい
        getSupportLoaderManager();
    }

ただ画面回転で起こるということは、状況によってはIntentなんかで画面遷移した際にも
起こりそうで嫌です…
destroyまで走れば一緒かな…

Fragment#getLoaderManagerもFragmentActivity#getSupportLoaderManagerも
結局はFragmentActivity#getLoaderManagerを呼んでいますしなんでなんだろ

どっちもonDestroy時にLoaderManager#doDestroy呼んでいるし



何れにしても、なんかうまくいきませんでした。
「使い方がおかしいだろ」とかあったら教えてください。

0 件のコメント:

コメントを投稿