最近はもっぱらAndroidのSupport LibraryでFragmentActivityな日々ですが、AsyncTaskLoaderが良いというウワサなのでAsyncTaskを置き換える程度の気持ちで使ったらガッツリハマりました。
今回の問題はAsyncTaskLoaderを実装したActivityから他のActivityに移動し、戻るボタンで戻ってきたときに勝手にloadInBackgroundが実行されてしまう問題です。
結論としては、何も考えずに以下サイトのdeliverResult以下全部自分のAsyncTaskLoaderにコピーしておけばいいです。
android – onLoadFinished not called after coming back from a HOME button press – Stack Overflow
一応転載しておきます。
public abstract class AsyncLoader<D> extends AsyncTaskLoader<D> { private D data; public AsyncLoader(Context context) { super(context); } @Override public void deliverResult(D data) { if (isReset()) { // An async query came in while the loader is stopped return; } this.data = data; super.deliverResult(data); } @Override protected void onStartLoading() { if (data != null) { deliverResult(data); } if (takeContentChanged() || data == null) { forceLoad(); } } @Override protected void onStopLoading() { // Attempt to cancel the current load task if possible. cancelLoad(); } @Override protected void onReset() { super.onReset(); // Ensure the loader is stopped onStopLoading(); data = null; } }
この例では抽象クラスなので同じようなことをする場合はAsyncLoaderをextendsすればいいですね。
こちらも大体同じ構成のようです。
時代は AsyncTask より AsyncTaskLoader – ぐま あーかいぶ
呼び出しに時間のかかるサーバサイドのAPIの処理に利用しようとして、ActivityのonCreateで
getSupportLoaderManager().initLoader(0, null, mCallbacks);
として、呼び出しのたびに
Bundle bundle = new Bundle(1); bundle.putString(KEY_PARAM_1, "something"); getSupportLoaderManager().restartLoader(0, bundle, mCallbacks);
として呼び出していました。
戻るボタンで戻ってくると、これらを通らずにLoaderがonStartLoadingを実行するので、ここでforceLoadを実行していると、loadInBackgroundが実行されてしまいます。
まぁ、結局問題は条件をつけずに
@Override protected void onStartLoading() { forceLoad(); }
にしてしまっていたことなので、気をつけましょうという話です。
Loaderは概念もうちょっと理解しないと、危ないですね。