AsyncLoader - Android中的异步加载器

来源:互联网 发布:linux 分辨率 编辑:程序博客网 时间:2024/06/05 06:52

Loader设计用于从数据源加载某类数据(如对象)。数据源可以是磁盘、数据库、ContentProvider、网络或者另一进程。loader可在不阻塞主线程的情况下获取并发送结果数据给接受者。

为什么使用loader而不直接使用AsyncTask呢

  • 一个最有说服力的理由是:因设备旋转等原因发生配置改变时,loaderManager可保证组件的loader及其数据不会丢失。
  • 如果使用AsyncTask加载数据,配置发生改变时,我们就必须亲自管理其生命周期并保存它获取的数据。虽然我们经常使用保留的Fragment(使用setRetainInstance(true)方法)解决了这些麻烦问题,但某些场景下,我们还是必须亲自介入并编写应对代码,才能保证一切尽在掌握。

Loader类继承结构图

这里写图片描述

public class CursorLoader extends AsyncTaskLoader<Cursor> {public abstract class AsyncTaskLoader<D> extends Loader<D> {public class Loader<D> {
  • 由继承关系以及类的定义可以看出:Loader和AsyncTaskLoader是泛型,而CursorLoader是继承AsyncTaskLoader并且是cursor的泛型,所以CursorLoader使用来实现数据库、ContentProvider的异步加载。

AsyncTaskLoader的使用

1. 创建AsyncTaskLoader的实现类。

public abstract class SimpleCursorLoader extends AsyncTaskLoader<Cursor> {    private Cursor mCursor;    public SimpleCursorLoader(Context context) {        super(context);    }    /* 在子线程里运作 */    @Override    public abstract Cursor loadInBackground();    /* 在ui 线程里运作 */    @Override    public void deliverResult(Cursor cursor) {        if (isReset()) {            // An async query came in while the loader is stopped            if (cursor != null) {                cursor.close();            }            return;        }        Cursor oldCursor = mCursor;        mCursor = cursor;        if (isStarted()) {            super.deliverResult(cursor);        }        if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {            oldCursor.close();        }         }    @Override    protected void onStartLoading() {        if (mCursor != null) {            deliverResult(mCursor);        }        if (takeContentChanged() || mCursor == null) {            forceLoad();        }    }    @Override    protected void onStopLoading() {        cancelLoad();    }    @Override    public void onCanceled(Cursor cursor) {        if (cursor != null && !cursor.isClosed()) {            cursor.close();        }    }    @Override    protected void onReset() {        super.onReset();        onStopLoading();        if (mCursor != null && !mCursor.isClosed()) {            mCursor.close();        }        mCursor = null;    }}
  • loadInBackground( )在子类中实现,用于在后台中加载cursor。
  • deliverResult(Cursor)负责处理两件事:如果loader启动了(这表示数据可以发送了),超类版本的deliverResult(…)方法会被调用。如果旧的cursor不再需要,它会被关闭以释放资源。现有cursor可能会被缓存或重新发送,因此在关闭旧的cursor前,必须确认新旧cursor并不相同。

2.创建LoaderCallback< Cursor >或者让fragment实现LoaderCallback< Cursor >

    @Override    public Loader onCreateLoader(int id, Bundle args) {        SimpleCursorLoader loader = new SimpleCursorLoader(context);        return loader;    }    @Override    public void onLoadFinished(Loader loader, Object data) {               //刷新UI     }    @Override    public void onLoaderReset(Loader loader) {            //当没有数据加载时,该方法会被调用    }

3.在Fragment或者Activity中添加

getLoaderManager().initLoader(id,bundle,callback);

- 该方法有三个参数:
1. id用来区分多个Loader
2. bundle用来传递数据
这两个参数将会传递到callback中的 onCreateLoader(int id , Bundle args) 中。
3. callback用来实现回调

4.设置数据监听

  1. 在改变数据的地方添加getContentResolver().notifyChange(uri, null);方法用于通知观察者数据发生改变
  2. callbackloadInBackground中添加代码
    cursor.registerContentObserver(new ForceLoadContentObserver());    cursor.setNotificationUri(context.getContentResolver(), uri);

两处的uri必须相同才能实现观察者模式。

以上就是AsyncTaskLoader的简单使用,如果想参考具体实现,可以查看Android官网reference中AsyncTaskLoader的实现或者阅读Android编程权威指南

0 0