Loader是一种封装特别好的异步加载资源的方式,我们可以通过继承AsyncTaskLoader或者Loader来实现我们的异步加载资源,也可以通过谷歌原生的子类来实现一些简单的异步资源加载,比如CursorLoader就比较适用于加载数据库,ContentProvider或者手机中的图片联系人等资源。
为了更好的体验Loader的强大,我们可以尝试一下使用CursorLoader,然后再深入学习一下
AsyncTaskLoader的使用以及实现机制。
通过将对应的 URI 以及其他的查询条件传递给CursorLoader及其子类,便可让其在后台高效地加载数据,等数据加载完成了便会返回一个 Cursor.,然后我们通过实现Loadermanager.LoaderCallbacks接口,在onLoadFinished(final Loader loader, final Cursor data)中取到我们需要的数据。
首先我们需要对CursorLoader继承,实现其子类,并且实现构造器,如下:
Public class ChildOfCursorLoader extend CursorLoader {
public BoundCursorLoader( final Context context, final Uri uri,
final String[] projection, final String selection, final String[] selectionArgs,
final String sortOrder) {
super(context, uri, projection, selection, selectionArgs, sortOrder);
}
}
当然我们可以将其查询等条件设置为静态变量,如果是这样的话,我们可以看出一个子类只可以实现一种查询操作,在这种情况下我们可以使用单例模式,这样可以节省我们的内存空间,至于是懒汉还是饿汉,根据情况选择,同时要注意多线程模式下要保证安全。
当然最好还是不指定的方式更好一些,这样更加灵活,我们可以Loadermanager.LoaderCallbacks接口中的onCreateLoader()中定制自己的查询条件。
紧接着我们通过实现Loadermanager.LoaderCallbacks接口来加载数据。
先来了解一下这个接口的函数有哪些:
LoaderManager.LoaderCallbacks 接口包括以下方法:
onCreateLoader(int id,final Bundle args):针对指定的 ID 进行实例化并返回新的 Loader,当我们尝试访问加载器时(例如,通过LoaderManager. initLoader()),该方法将检查是否已存在由该 ID 指定的加载器。如果没有,它将触发 LoaderManager.LoaderCallbacks 中的 onCreateLoader() 方法。在此方法中,我们可以创建加载器,通过这个方法将返回 CursorLoader,但我们也可以实现自己的 Loader 子类。
onLoadFinished():将在先前创建的加载器完成加载时调用,当先前创建的加载器完成加载时,将会调用此方法。该方法必须在为此加载器提供的最后一个数据释放之前调用。此时,我们应该移除所有使用的旧数据(因为它们很快就会被释放),但不要自行释放这些数据,因为这些数据归加载器所有,加载器会处理它们。
onLoaderReset():当创建好的Loader被reset时调用此方法,会清空已绑定数据,此时CreatLoader会重新执行。
以下为实现接口的代码:
Public class myLoaderCallback implements Loadermanager.LoaderCallbacks<Cursor> {
@overide
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
Uri baseUri;
if (mCurFilter != null) {
baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
Uri.encode(mCurFilter));
} else {
baseUri = Contacts.CONTENT_URI;
}
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");
}
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
Mdata = data;
}
public void onLoaderReset(final Loader<Cursor> generic) {
mlistener.onDataCursorUpdated(generic);
}
}
通过上述代码我们可以看到,我们可以通过onCreateLoader()定制自己所需要的loader,从onLoadFinished中获取数据,最后在onLoaderReset()中获取更新后的Loader,然后对原本的数据进行处理。之后只需要两条代码就可以完成我们所需要的跟中查询。
LoaderManager mLoaderManager = getLoaderManager();
mLoaderManager.initLoader(LoaderId,null,callbacks);
值得注意的是getLoaderManager()这个方法通过activity或者Fragment的子类对象才可以调用。
这样我们就可以在callbacks.onLoadFinished(Loader loader, Cursor data)中获取数据,其参数data就是我们需要的数据。
如果对如何使用存在疑问的可以看一下这篇文章:
https://juejin.im/post/5a27c56e51882535cd4ab5af#heading-4
我们在使用Loader的时候,也可以结合工厂模式使用,就只需要在LoaderCallback通过一些简单的条件判断需要create哪种Loader,接下来两个方法也是如此。因为最近在学习代码,看过好几种使用方法,所以记录一下。