Loader机制简单使用

96
麦兜叮叮当
2017.09.19 12:13* 字数 452

Loader是一个很有意思的异步加载工具,能够很优雅的监听数据更新,并传递给我们。而且Loader非常聪明,接下来简单介绍一下它的使用方法以及它聪明的地方。

Loader使用其实是很简单的,逻辑很清晰:
1.通过Activity\Fragment的getLoaderManager().initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callBack)进行初始化。id代表当前Loader的标识,虽然一个Fragment或者Activity中只存在一个 LoaderManager,但是可以存在多个Loader,此id用于标识不同的Loader;args则是传递给Loader的Bundle类型的参数;callBack则是一个回调。

2.接着我们实现 LoaderManager.LoaderCallbacks<D>接口的三个回调方法。

onCreate()  --  创建一个Loader并且返回给LoaderManager(一般使用CursorLoader)
onLoaderFinished() -- Loader加载完成以后调用 ,返回结果
onLoaderReset() -- Loader重置以后,不加载数据

3.继承AsyncTaskLoader,重写loadInBackground方法,这里方法运行在子线程,可以执行耗时程序。当耗时操作执行完毕之后,会通过回调方法onLoaderFinished告诉我们。

ok,完整小例子奉上:

public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<String>{

    private LoaderText mLoaderText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mLoaderText = new LoaderText(this);
        getLoaderManager().initLoader(2, null, this);
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //通知有数据更新
                    mLoaderText.onContentChanged();
                }
            }
        }).start();
    }

    @Override
    public Loader<String> onCreateLoader(int i, Bundle bundle) {
        Log.d("~", "onCreateLoader");
        return mLoaderText;
    }

    @Override
    public void onLoadFinished(Loader<String> loader, String s) {
        Log.d("~", "onLoadFinished " + s);
    }

    @Override
    public void onLoaderReset(Loader<String> loader) {
        Log.d("~", "onLoaderReset");
    }
}
public class LoaderText extends AsyncTaskLoader<String> {

    public LoaderText(Context context) {
        super(context);
    }

    @Override
    public String loadInBackground() {
        Log.d("~", "loadInBackground");
        Random random = new Random();
        int mNeededBreads =random.nextInt(100);
        try {
            //模拟耗时操作
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return String.valueOf(mNeededBreads);
    }
}

上面很关键的一句代码:mLoaderText.onContentChanged();
如果我们有数据更新,必须通过调用这个方法来通知AsyncTaskLoader。

还有一个类需要提一下CursorLoader,作用与AsyncTaskLoader类似,不过CursorLoader用于加载contentProvider里面提供的数据,可以实现动态监听,而AsyncTaskLoader是异步任务的加载,需要我们手动提示数据更新。

当然刚才我们说了Loader很聪明,聪明在什么地方呢,当我们告诉AsyncTaskLoader有数据更新,它会尝试重新获取数据,如果获取到的数据与之前是完全相同的话,是不会回调onLoadFinished方法的。大家可以尝试一下。

技术分享