Loader简单使用
AsyncTaskLoader VS AsyncTask
- 数据影响UI还是的用AsyncTask为好
- AsyncTaskLoader主要针对的是Activity配置的变化 不会引起数据的变化 同时数据源的变化可以实现自动更新
所以 AsyncTask也不能被抛弃 不过AsyncTask在使用的时候要做好相关的配置
前面看到函数响应式编程 用RxJava系列RxAndroid来处理异步操作等等 我试着写了一个简单 但是还是不太熟悉
打算这个还是很有必要看就下 大家有兴趣可以去看看
贴两个地址 学习响应式编程
https://github.com/ReactiveX/RxAndroid
https://github.com/lzyzsd/Awesome-RxJava/blob/master/README.md
简单分析下实现过程 根据源码查看 下面是使用中的代码
getLoaderManager().initLoader(0, null, mCallbacks);
mCallbacks = new LoaderManager.LoaderCallbacks<List<String>>() {
@Override
public Loader<List<String>> onCreateLoader(int id, Bundle args) {
if (mBaker == null) {
mBaker = new Baker(MainActivity.this);
}
return mBaker;
}
@Override
public void onLoadFinished(Loader<List<String>> loader, List<String> data) {
list.addAll(data);
myAdpater.notifyDataSetChanged();
//数据处理完的回调
LogUtils.e("sell " + data.size() + " breads");
}
@Override
public void onLoaderReset(Loader<List<String>> loader) {
}
};
查看initLoader来到LoaderManagerImpl 是LoaderManager的实现类 所有的具体实现都在这里面
public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {
if (mCreatingLoader) {
throw new IllegalStateException("Called while creating a loader");
}
//集合中获取指定的LoaderInfo
LoaderInfo info = mLoaders.get(id);
if (DEBUG) Log.v(TAG, "initLoader in " + this + ": args=" + args);
if (info == null) {
// 不存在就创建一个LoaderInfo
info = createAndInstallLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback);
if (DEBUG) Log.v(TAG, " Created new loader " + info);
} else {
if (DEBUG) Log.v(TAG, " Re-using existing loader " + info);
info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback;
}
if (info.mHaveData && mStarted) {
// If the loader has already generated its data, report it now.
info.callOnLoadFinished(info.mLoader, info.mData);
}
return (Loader<D>)info.mLoader;
}
具体创建的源码createAndInstallLoader 方法
private LoaderInfo createAndInstallLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<Object> callback) {
try {
mCreatingLoader = true;
//创建LoaderInfo
LoaderInfo info = createLoader(id, args, callback);
//创建后的操作 处理
installLoader(info);
return info;
} finally {
mCreatingLoader = false;
}
}
void installLoader(LoaderInfo info) {
mLoaders.put(info.mId, info);
if (mStarted) {
// The activity will start all existing loaders in it's onStart(),
// so only start them here if we're past that point of the activitiy's
// life cycle
//LoaderInfo的start()开启
info.start();
}
}
现在看看info.start(); 这个方法具体干了什么
void start() {
if (mRetaining && mRetainingStarted) {
// Our owner is started, but we were being retained from a
// previous instance in the started state... so there is really
// nothing to do here, since the loaders are still started.
mStarted = true;
return;
}
if (mStarted) {
// If loader already started, don't restart.
return;
}
mStarted = true;
if (DEBUG) Log.v(TAG, " Starting: " + this);
if (mLoader == null && mCallbacks != null) {
//回调操作 在Activity中或者Fragment中 这里是我们上面使用的三个回调的第一个
mLoader = mCallbacks.onCreateLoader(mId, mArgs);
}
if (mLoader != null) {
if (mLoader.getClass().isMemberClass()
&& !Modifier.isStatic(mLoader.getClass().getModifiers())) {
throw new IllegalArgumentException(
"Object returned from onCreateLoader must not be a non-static inner member class: "
+ mLoader);
}
if (!mListenerRegistered) {
//这里是注册 将自己给注册到Loader的提供的接口上 让Loader回调这里实现相关操作 因为后续使用AsyncTaskLoader回调的时候 可以操作LoaderInfo的Callback回调
mLoader.registerListener(mId, this);
mLoader.registerOnLoadCanceledListener(this);
mListenerRegistered = true;
}
//loader开始载入
mLoader.startLoading();
}
}
可以看看mLoader.registerListener(mId, this); 这个方法里面做了什么操作
public void registerListener(int id, OnLoadCompleteListener<D> listener) {
if (mListener != null) {
throw new IllegalStateException("There is already a listener registered");
}
mListener = listener;
mId = id;
}
看看 mLoader.startLoading();因为使用的是AsyncTaskLoader我们就看我们在使用AsyncTaskLoader中的实现
@Override
protected void onStartLoading() {
forceLoad();
}
public void forceLoad() {
onForceLoad();
}
@Override
protected void onForceLoad() {
super.onForceLoad();
cancelLoad();
mTask = new LoadTask();
if (DEBUG) Log.v(TAG, "Preparing load: mTask=" + mTask);
//开始执行异步任务
executePendingTask();
}
看看LoadTask 只看一些核心代码 就是一个AsyncTask的子类 里面的逻辑和AsyncTask一样子线程完后回到UI更新
final class LoadTask extends AsyncTask<Void, Void, D> implements Runnable {
private final CountDownLatch mDone = new CountDownLatch(1);
// Set to true to indicate that the task has been posted to a handler for
// execution at a later time. Used to throttle updates.
boolean waiting;
/* Runs on a worker thread */
@Override
protected D doInBackground(Void... params) {
*****省略****
D data = AsyncTaskLoader.this.onLoadInBackground();
return data;
*****省略****
}
/* Runs on the UI thread */
@Override
protected void onPostExecute(D data) {
if (DEBUG) Log.v(TAG, this + " onPostExecute");
try {
//后台任务完成后 来到这里 这里按照我们的逻辑来看应该是执行LoaderManager的onfinish()完成的回调
AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);
} finally {
mDone.countDown();
}
}
/* Runs on the UI thread */
@Override
protected void onCancelled(D data) {
if (DEBUG) Log.v(TAG, this + " onCancelled");
try {
AsyncTaskLoader.this.dispatchOnCancelled(this, data);
} finally {
mDone.countDown();
}
}
}
看看这个里面 AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);
void dispatchOnLoadComplete(LoadTask task, D data) {
if (mTask != task) {
if (DEBUG) Log.v(TAG, "Load complete of old task, trying to cancel");
dispatchOnCancelled(task, data);
} else {
if (isAbandoned()) {
// This cursor has been abandoned; just cancel the new data.
onCanceled(data);
} else {
commitContentChanged();
mLastLoadCompleteTime = SystemClock.uptimeMillis();
mTask = null;
if (DEBUG) Log.v(TAG, "Delivering result");
//分发结果 胜利就在眼前
deliverResult(data);
}
}
}
public void deliverResult(D data) {
if (mListener != null) {
//这里就是上面LoaderManagerImpl 注册的时候把自己注册上去的回调
mListener.onLoadComplete(this, data);
}
}
//最后来到回调 mListener.onLoadComplete(this, data); 的具体实现 去掉不重要的代码
@Override
public void onLoadComplete(Loader<Object> loader, Object data) {
****省略****
if (mData != data || !mHaveData) {
mData = data;
mHaveData = true;
if (mStarted) {
callOnLoadFinished(loader, data);
}
}
****省略****
}
void callOnLoadFinished(Loader<Object> loader, Object data) {
if (mCallbacks != null) {
String lastBecause = null;
if (mActivity != null) {
lastBecause = mActivity.mFragments.mNoTransactionsBecause;
mActivity.mFragments.mNoTransactionsBecause = "onLoadFinished";
}
try {
if (DEBUG) Log.v(TAG, " onLoadFinished in " + loader + ": "
+ loader.dataToString(data));
//到这里成功实现onLoadFinished 方法的回调 数据加载成功
mCallbacks.onLoadFinished(loader, data);
} finally {
if (mActivity != null) {
mActivity.mFragments.mNoTransactionsBecause = lastBecause;
}
}
mDeliveredData = true;
}
}
上面就是整个数据加载完成回调实现的过程 跑了一遍
然后我们一般在使用的时候会用上自定更新数据 也就是数据更新 我们会自动加载数据 其实也就是要用了观察者模式 我们可以通过广播或者Eventbus来实现
这里用广播 看看 内部原理
static class Bakery extends BroadcastReceiver {
final Baker mBaker;
public static String CUSTOMER_ACTION = "com.daemon.demo" ;
public Bakery(Baker baker) {
mBaker = baker;
IntentFilter filter = new IntentFilter(CUSTOMER_ACTION);
baker.getContext().registerReceiver(this, filter);
}
@Override public void onReceive(Context context, Intent intent) {
//主要是这个方法 来通知更新
mBaker.onContentChanged();
}
}
public void onContentChanged() {
if (mStarted) {
// 发现和上面的Loader onstartLoading那一步
forceLoad();
} else {
// This loader has been stopped, so we don't want to load
// new data right now... but keep track of it changing to
// refresh later if we start again.
mContentChanged = true;
}
}
现在来一个例子 例子是网上看着别人的 自己用在ListView显示 一个添加数据的按钮
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.lvshow = (ListView) findViewById(R.id.lv_show);
this.btadd = (Button) findViewById(R.id.bt_add);
mBaker = new Baker(this);
mBakery = new Bakery(mBaker,this);
list=new ArrayList<String>();
myAdpater=new MyAdpater(this,list);
lvshow.setAdapter(myAdpater);
mCallbacks = new LoaderManager.LoaderCallbacks<List<String>>() {
@Override
public Loader<List<String>> onCreateLoader(int id, Bundle args) {
if (mBaker == null) {
mBaker = new Baker(MainActivity.this);
}
return mBaker;
}
@Override
public void onLoadFinished(Loader<List<String>> loader, List<String> data) {
list.addAll(data);
myAdpater.notifyDataSetChanged();
//面包师完成面包烤制
LogUtils.e("sell " + data.size() + " breads");
}
@Override
public void onLoaderReset(Loader<List<String>> loader) {
}
};
//面包师开始工作
getLoaderManager().initLoader(0, null, mCallbacks);
btadd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Bakery.CUSTOMER_ACTION);
sendBroadcast(intent);
}
});
}
Baker
public class Baker extends AsyncTaskLoader<List<String>> {
public Baker(Context context) {
super(context);
}
@Override
public List<String> loadInBackground() {
List<String> breads = new ArrayList<String>();
//获得当前需要做的面包
for (int i = 0; i < 5; i++) {
//制作面包,耗时操作
breads.add("123"+i);
}
//面包制作完成
return breads;
}
@Override
public void deliverResult(List<String> data) {
super.deliverResult(data);
}
@Override
protected void onStartLoading() {
forceLoad();
}
@Override
protected void onStopLoading() {
cancelLoad();
}
@Override
protected void onReset() {
super.onReset();
}
}
Bakery
public class Bakery extends BroadcastReceiver {
final Baker mBaker;
public static String CUSTOMER_ACTION = "com.daemon.demo" ;
public Bakery(Baker baker , Context context) {
mBaker = baker;
IntentFilter filter = new IntentFilter(CUSTOMER_ACTION);
context.registerReceiver(this, filter);
}
@Override
public void onReceive(Context context, Intent intent) {
mBaker.onContentChanged();
}
}
基本就是这样了 用起来也方便 还是那个有点 频幕旋转 Activity生命周期的变化等等一切影响Loader都帮你处理 你只关心加载数据就行 我平时也没用过这个 看着源码理一理还是挺好