最近はもっぱら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は概念もうちょっと理解しないと、危ないですね。

HOMMA Teppei

