9
7

More than 5 years have passed since last update.

【Android】LoaderManagerを使い回す方法

Posted at

1. 概要

Androidで同じLoaderManagerを使い回す方法のメモ

2. やりたかったこと

最初に定義したLoaderManagerとAsyncTaskLoaderは以下の通り。
文字列を受け取って非同期でログに出力するだけ。

MyLoaderManager.java
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のインスタンスを一つ作成し、何度も使い回ししたかった。

MainActivity.java

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

9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7