1. 概要
Androidで同じLoaderManagerを使い回す方法のメモ
2. やりたかったこと
最初に定義したLoaderManagerとAsyncTaskLoaderは以下の通り。
文字列を受け取って非同期でログに出力するだけ。
public class MyLoaderManager implements LoaderManager.LoaderCallbacks<String> {
private Activity activity;
public MyLoaderManager(Activity _activity) {
this.activity = _activity;
}
public void doTask(String text) {
Bundle bundle = new Bundle();
bundle.putString("text", text);
activity.getLoaderManager().initLoader(1, bundle, this);
}
@Override
public Loader<String> onCreateLoader(int id, Bundle args) {
// TODO Auto-generated method stub
MyLoader loader = new MyLoader(activity, args.getString("text"));
loader.forceLoad();
return loader;
}
@Override
public void onLoadFinished(Loader<String> loader, String data) {
// TODO Auto-generated method stub
Log.d("TAG", data);
}
@Override
public void onLoaderReset(Loader<String> loader) {
// TODO Auto-generated method stub
}
}
class MyLoader extends AsyncTaskLoader<String> {
private String text;
public MyLoader(Context _context, String _text) {
super(_context);
this.text = _text;
}
@Override
public String loadInBackground() {
// TODO Auto-generated method stub
return text;
}
}
やりたかったこととしては、下記のようにMyLoaderManagerのインスタンスを一つ作成し、何度も使い回ししたかった。
public class MainActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyLoaderManager myLoaderManager = new MyLoaderManager(this);
myLoaderManager.doTask("hogehoge");
myLoaderManager.doTask("fugafuga");
myLoaderManager.doTask("piyopiyo");
}
}
3. 問題点:二度目以降、onCreateLoaderが呼ばれない
どうやら上で定義したコードだと、onCreateLoaderが一回しか呼ばれないらしい。
したがって、
myLoaderManager.doTask("hogehoge");
myLoaderManager.doTask("fugafuga");
myLoaderManager.doTask("piyopiyo");
と呼び出しても、ログにはhogehogeしか出力されていなかった。
3.1 対処法1:IDを設定する
原因はココ。
activity.getLoaderManager().initLoader(1, bundle, this);
どうやらinitLoader
は、指定したIDごとに一度しか呼ばれないらしい。
IDとはinitLoader
の第一引数のやつ。
そこで上記のコードを、
public void doTask(int id, String text) {
Bundle bundle = new Bundle();
bundle.putString("text", text);
activity.getLoaderManager().initLoader(id, bundle, this);
}
と訂正し、呼び出しを
myLoaderManager.doTask(1, "hogehoge");
myLoaderManager.doTask(2, "fugafuga");
myLoaderManager.doTask(3, "piyopiyo");
として、IDを変更してあげればちゃんと全部呼ばれた。
ただ、毎回個別にIDを設定するのは面倒臭い。
そこで次のような修正をした。
3.2 対処法2:restartLoaderを使う
同一のIDで使い回したいときは、initLoader
の代わりにrestartLoader
を使う。
activity.getLoaderManager().restartLoader(id, bundle, this);
こうすることによってonCreateLoaderを再度呼び出すことができる。
しかし、上記のMainActivity
のように連続でLoaderを呼んだとき、既存のLoaderの処理が終わってなかったら途中で破棄されて新しいLoaderの処理を始めてしまうっぽいので注意。
そういうときは、Callbackで前回のLoaderの終了を検知してやればいいかも。
4. 参考
http://yuki312.blogspot.jp/2012/02/loadermanager.html
http://d.hatena.ne.jp/Kyakujin/20130528/1369729549