使用AsyncTask加载数据时,如果遇到设备配置改变,或用户点击后退键等操作,
需要主动管理AsyncTask的生命周期,同时需要保存好下载数据。
此时,可以考虑使用AsyncTaskLoader,它继承自Loader(原生和支持库中均有实现)。
在遇到类似设备旋转等场景时,LoaderManager会帮我们妥善管理Loader及其加载的数据。
而且,LoaderManager还负责启动和停止loader,以及管理loader的生命周期。
当设备配置发生改变后,如果初始化一个已经加载完数据的loader,它能立即提交数据,
而不是再次尝试获取数据。
AsyncTaskLoader的基本用法如下所示,
主要包括创建回调接口、定义AysncTaskLoader的子类
及利用LoaderManager启动整个加载流程:
public class PhotoGalleryFragment extends Fragment{
.............
//指定Loader对应的id
public static final int mLoaderId = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
//定义一个回调接口,一个callback可以监听多个loader
//模板参数为AysncTaskLoader加载数据的返回值
LoaderManager.LoaderCallbacks<List<GalleryItem>> callback =
new LoaderManager.LoaderCallbacks<List<GalleryItem>>() {
//LoaderManager创建Loader时,回调该接口
@Override
public Loader<List<GalleryItem>> onCreateLoader(int id, Bundle args) {
//可以根据id创建出不同的Loader
//要求创建出的loader,不能是非静态内部类
//原因应该是避免内存泄露
if (id == mLoaderId) {
Log.d("ZJTest", "onCreateLoader");
return new FetchItemsLoader(getActivity());
} else {
return null;
}
}
//FetchItemsLoader加载完数据时,就会回调该接口
@Override
public void onLoadFinished(Loader<List<GalleryItem>> loader, List<GalleryItem> data) {
//同样可以根据id进行不同的操作
if (loader.getId() == mLoaderId) {
Log.d("ZJTest", "onLoadFinished");
//可以进行更新界面等操作
mGalleryItems = data;
setupAdapter();
}
}
@Override
public void onLoaderReset(Loader<List<GalleryItem>> loader) {
}
};
//利用LoaderManager启动Loader,指定loader对应的id、参数和回调接口
getLoaderManager().restartLoader(mLoaderId, null, callback);
}
...................
//AsyncTaskLoader同样为抽象类,在模板参数中指定loadInBackground的返回值
private static class FetchItemsLoader extends AsyncTaskLoader<List<GalleryItem>> {
FetchItemsLoader(Context context) {
super(context);
}
//必须实现这个方法,forceLoad为父类接口
//调用该接口后,才会执行loadInBackground的操作
@Override
protected void onStartLoading() {
Log.d("ZJTest", "onStartLoading");
forceLoad();
}
//返回值将会传回给callback的onLoadFinished接口
@Override
public List<GalleryItem> loadInBackground() {
Log.d("ZJTest", "loadInBackground");
return new ImageFetcher().fetchItems();
}
}
}
我们运行一下该段代码,log类似于:
02-14 15:41:01.080 11297-11297/stark.a.is.zhang.photogallery D/ZJTest: onCreateLoader
02-14 15:41:01.089 11297-11297/stark.a.is.zhang.photogallery D/ZJTest: onStartLoading
02-14 15:41:01.095 11297-11313/stark.a.is.zhang.photogallery D/ZJTest: loadInBackground
02-14 15:41:01.562 11297-11297/stark.a.is.zhang.photogallery D/ZJTest: onLoadFinished