Android学习笔记12——用户界面之Loader类

本文介绍如何使用Loader在Activity或Fragment中轻松实现异步数据加载。Loader具备在配置更改时自动恢复加载位置等功能,通过几个步骤即可实现数据的异步加载和管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Loader使得在Activity或者Fragment中更加容易地异步加载数据。Loader有以下三个特性:

1、他们可以在任意一个Acticvity或者Fragment中使用;

2、他们提供异步数据的加载;

3、当内容改变时,他们控制他们的数据源传输新的结果给Activity或者Fragment

4、当配置改变的时候他们被重新创建的时候,他们自动重新连接到上一次loader的指针所在的地方,因此不需要重新查询出数据。

那么我们如何在我们的Activity或者Fragment中使用Loader类呢?

一个应用程序用到loader基本需要包含以下几步:

1、一个Activity或者Fragmnet;

2、一个LoaderManager实例;

3、一个CurLoader实例用来加载ContentProvider返回的数据。或者,你也可以实现自己的Loader或者AsyncTaskLoader的子类用来加载其他资源的数据;

4、实现LoaderManager.LoaderCallbacks。在这个方法中实例化load或者管理已经存在的loader;

5、一种展示loader的数据的方式,例如SimpleCursorAdapter.

6、一个数据源,例如当我们使用CurLoader的时候用Content Provider。

如何开启一个Loader呢?

LoaderManager在一个Activity或者Fragment中可以管理一个或者多个Loader,但是每一个Fragment或者Activity仅仅有一个LoaderManager。我们一般在Activity的onCreate方法中或者onActivityCreated方法中实例化一个Loader对象。

// Prepare the loader.  Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
这个initLoader方法需要三个参数:

1、一个Loader实例独一无二的ID;

2、在这个构造方法中是一个可选参数,一般为null;

3、一个LoaderManager.LoaderCallbacks的实现类。LoaderManager调用这个实现类去记录loader事件。在上面这个例子中,这个类本身实现了LoaderManager.LoaderCallbacks方法,因此传递一个this引用它自身。

这个initLoader方法调用使得这个loader被初始化和激活,这个方法可以返回两个结果。

如果这个Loader指定一个已经存在的loader ID,那么最近一次实例化的loader被重新利用;

但是如果这个Loader指定一个不能存在的Loader ID,initLoader()方法触发LoaderManager.LoaderCallbacks接口的onCreatedLoader方法,在这个方法中你实例化并返回一个新的loader对象。

无论以上的两种情况的哪一个,这个LoaderManager.LoaderCallbacks方法实现类和loader相关,并且在这个loader的状态改变的时候这个实现类就会被调用。如果这个接口在调用的时候,这个调用者的状态是开启状态并且这个loader已经存在,数据已经生成,系统会立刻自动调用onLoadFinished方法,因此你必须为这个要发生的准备着。

注意:initLoader方法返回被创建成功的loader,但是你不需要占用它的一个引用,LoaderManager会自动管理loader的生命周期。LoaderManager会根据需要开启和关闭一个Loader,管理loader的状态和它相关的内容。在整个应用过程中你会很少和loaders进行交互。在特殊的事件发生的时候,最常用的是在LoaderManager.LoaderCallbacks方法中阻塞数据加载的进程。

重启一个Loader

当我们使用loader的时候正如上面展示的一样,它使用了一个已经存在的ID的loader。如果不存在,则就会创建一个新的。但是有的时候我们想要丢弃掉我们旧的数据并且重新开启一个loader。这个时候我们就需要用到restartLoader方法。

public boolean onQueryTextChanged(String newText) {
    // Called when the action bar search text has changed.  Update
    // the search filter, and restart the loader to do a new query
    // with this filter.
    mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
    getLoaderManager().restartLoader(0, null, this);
    return true;
}
如何使用LoaderManager的Callbacks各种回调方法?

LoaderManager.LoaderCallbacks是让一个客户端与LoaderManager交互的回调接口。

Loader,比较特殊的例如,CursorLoader,可以在他们停止的时候也可以保持它的数据。这就允许应用程序在Activity或者Fragment的onStop和onStart方法之间保持他们数据,这就使得当用户在返回到应用程序时,不必重新加载数据。

LoaderManager.LoaderCallBacks包括这些方法。

onCreateLoader()——初始化并且返回一个被给与ID的新的Loader;

onLoadFinished()——当一个事先创建的Loader完成它的load的时候调用;

onLoadReset()——当一个事先创建的Loader被reset并且使得数据不可用的时候调用;

onCreateLoader方法:

当你试图访问一个Loader的时候,系统会自动检查被指定ID的loader是否存在,如果不存在系统会触发LoaderManager.LoaderCallbacks的onCreateLoader方法,在这里创建一个新的Loader实例。我们可以使用系统定义好的,例如CursorLoader,也可以实现我们自己的load子类。

// If non-null, this is the current filter the user has provided.
String mCurFilter;
...
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    // This is called when a new Loader needs to be created.  This
    // sample only has one Loader, so we don't care about the ID.
    // First, pick the base URI to use depending on whether we are
    // currently filtering.
    Uri baseUri;
    if (mCurFilter != null) {
        baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                  Uri.encode(mCurFilter));
    } else {
        baseUri = Contacts.CONTENT_URI;
    }

    // Now create and return a CursorLoader that will take care of
    // creating a Cursor for the data being displayed.
    String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
            + Contacts.HAS_PHONE_NUMBER + "=1) AND ("
            + Contacts.DISPLAY_NAME + " != '' ))";
    return new CursorLoader(getActivity(), baseUri,
            CONTACTS_SUMMARY_PROJECTION, select, null,
            Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
}

onLoadFinished方法:

当新创建的loader完成加载数据时调用这个方法。这个方法被优先调用确保这个loader最后一次的数据被释放掉。这个时候你需要移除这些旧数据(即使它将要很快被释放掉)。

一旦loader知道应用程序不再使用它,它将要释放掉所有的数据。例如,如果一个数据是一个CursorLoader的一个Cursor,你不应该手动调用close()方法。如果这个cursor被CursorAdapt所替代,你应该使用swapCursor方法避免这个old Cursor被关闭。

// This is the Adapter being used to display the list's data.
SimpleCursorAdapter mAdapter;
...

public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    // Swap the new cursor in.  (The framework will take care of closing the
    // old cursor once we return.)
    mAdapter.swapCursor(data);
}
onLoaderReset方法

当一个之前创建的loader被重置的时候调用这个方法,这个方法使得要被重置的loader的数据不再可用,这个回调方法让你找出数据将要什么时候被释放掉,因此你能移除掉这个数据的引用。

SimpleCursorAdapter mAdapter;
...

public void onLoaderReset(Loader<Cursor> loader) {
    // This is called when the last Cursor provided to onLoadFinished()
    // above is about to be closed.  We need to make sure we are no
    // longer using it.
    mAdapter.swapCursor(null);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值