前面咱们比较关注的是LoaderManager
的原理和使用,若是咱们只是须要经过LoaderManager
来读取ContentProvider
封装的数据,那么采用系统已经定义好的CursorLoader
就能够了,可是有的时候,咱们的数据可能不是用ContentProvider
封装的,那么这时候就要学会如何定义本身的Loader
。bash
Loader<D>
类对于LoaderManager
来讲,它所看到的只是一个Loader
类,并调用它对应的方法,这些方法分为三类:异步
isXXX
startLoading/stopLoading/reset/cancelLoad/forceLoad/onReset
onXXX
public class Loader<D> {
public void deliverResult(D data) {
if (mListener != null) {
mListener.onLoadComplete(this, data);
}
}
public void deliverCancellation() {
if (mOnLoadCanceledListener != null) {
mOnLoadCanceledListener.onLoadCanceled(this);
}
}
//在startLoading执行完,且没有调用stopLoading或reset。
public boolean isStarted() {
return mStarted;
}
//在该状态下,不该该上报新的数据,而且应该保持着最后一次上报的数据直到被reset。
public boolean isAbandoned() {
return mAbandoned;
}
//没有启动,或者调用了reset方法。
public boolean isReset() {
return mReset;
}
<!-- 开始任务相关 -->
//开始任务。
public final void startLoading() {
mStarted = true;
mReset = false;
mAbandoned = false;
onStartLoading();
}
//开始任务后回调该方法,调用者重写该方法来加载数据。
protected void onStartLoading() {}
<!-- 取消任务相关 -->
//取消任务。
//1.返回 false 表示不能取消,有多是已经完成,或者 startLoading 尚未被调用。
//2.这不是一个马上的过程,由于加载是在后台线程中运行的。
public boolean cancelLoad() {
return onCancelLoad();
}
//调用者重写该方法来作取消后的操做。
protected boolean onCancelLoad() {
return false;
}
<!-- 强制刷新数据相关 -->
public void forceLoad() {
onForceLoad();
}
protected void onForceLoad() {}
<!-- 中止任务相关 -->
public void stopLoading() {
mStarted = false;
onStopLoading();
}
protected void onStopLoading() {}
<!-- 废弃任务相关 -->
public void abandon() {
mAbandoned = true;
onAbandon();
}
protected void onAbandon() {}
public void reset() {
onReset();
mReset = true;
mStarted = false;
mAbandoned = false;
mContentChanged = false;
mProcessingChange = false;
}
protected void onReset() {}
//获得mContentChanged的值,并把mContentChanged设为false
public boolean takeContentChanged() {
boolean res = mContentChanged;
mContentChanged = false;
mProcessingChange |= res;
return res;
}
//代表正在处理变化。
public void commitContentChanged() {
mProcessingChange = false;
}
//若是正在处理变化,那么中止它,而且把mContentChanged设为true。
public void rollbackContentChanged() {
if (mProcessingChange) {
mContentChanged = true;
}
}
//若是当前是start状态,那么收到变化的通知就当即从新加载,不然记录下这个标志mContentChanged。
public void onContentChanged() {
if (mStarted) {
forceLoad();
} else {
mContentChanged = true;
}
}
}
复制代码
能够看到,在Loader<D>
中,提供的是给LoaderManager
调用的接口,可是它并无真正地执行操做,而是在startLoading
等方法以后,提供了onStartLoading
等回调,让子类在这些回调中去执行对应的操做。ide
对于Loader
的使用者来讲,它更加但愿本身只用处理业务的逻辑,而不用再去关心如何把耗时的任务放到异步线程中。所以系统帮咱们实现了一个Loader
的实现类AsyncTaskLoader<D>
,里面封装了一个AsyncTask
用来执行耗时操做。可是它也是一个抽象类,咱们并不能直接使用它,而是让子类取实现它的loadInBackground
方法去处理本身的业务逻辑。post
public abstract class AsyncTaskLoader<D> extends Loader<D> {
static final String TAG = "AsyncTaskLoader";
static final boolean DEBUG = false;
final class LoadTask extends ModernAsyncTask<Void, Void, D> implements Runnable {
private final CountDownLatch mDone = new CountDownLatch(1);
//表示该Task已经被post到了Handler当中,用来作延时操做。
boolean waiting;
/* Runs on a worker thread */
@Override
protected D doInBackground(Void... params) {
try {
//在后台获取数据。
D data = AsyncTaskLoader.this.onLoadInBackground();
return data;
//onLoadInBackground代表要取消。
} catch (OperationCanceledException ex) {
if (!isCancelled()) {
//LoaderManager仍然指望获得结果,所以继续抛出这个异常。
throw ex;
}
return null;
}
}
//完成。
@Override
protected void onPostExecute(D data) {
if (DEBUG) Log.v(TAG, this + " onPostExecute");
try {
AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);
} finally {
mDone.countDown();
}
}
//取消。
@Override
protected void onCancelled(D data) {
if (DEBUG) Log.v(TAG, this + " onCancelled");
try {
AsyncTaskLoader.this.dispatchOnCancelled(this, data);
} finally {
mDone.countDown();
}
}
//因为实现了Runnable接口,在这里执行executePendingTask。
@Override
public void run() {
waiting = false;
AsyncTaskLoader.this.executePendingTask();
}
//在计数达到0时,一直等待,也就是onPostExecute或onCancelled回调了。
public void waitForLoader() {
try {
mDone.await();
} catch (InterruptedException e) {
// Ignore
}
}
}
private final Executor mExecutor;
volatile LoadTask mTask;
volatile LoadTask mCancellingTask;
long mUpdateThrottle;
long mLastLoadCompleteTime = -10000;
Handler mHandler;
public AsyncTaskLoader(Context context) {
this(context, ModernAsyncTask.THREAD_POOL_EXECUTOR);
}
private AsyncTaskLoader(Context context, Executor executor) {
super(context);
mExecutor = executor;
}
//从上一次loadInBackground返回,到下次Task执行的时间。
public void setUpdateThrottle(long delayMS) {
mUpdateThrottle = delayMS;
if (delayMS != 0) {
mHandler = new Handler();
}
}
@Override
protected void onForceLoad() {
super.onForceLoad();
cancelLoad(); //这里会回调onCancelLoad。
mTask = new LoadTask(); //新建一个Task。
executePendingTask(); //执行这个Task。
}
//cancelLoad后回调。
@Override
protected boolean onCancelLoad() {
//当前没有Task在执行。
if (mTask != null) {
//若是正在等待一个被取消的任务执行完毕,那么先取消最后的那个任务。
if (mCancellingTask != null) {
if (mTask.waiting) {
mTask.waiting = false;
mHandler.removeCallbacks(mTask);
}
mTask = null;
return false;
} else if (mTask.waiting) { //若是当前的任务正在等待被执行,那么直接取消它。
mTask.waiting = false;
mHandler.removeCallbacks(mTask);
mTask = null;
return false;
} else {
//若是当前的任务已经开始执行了,那么先记录下,赋值给mCancellingTask。
boolean cancelled = mTask.cancel(false);
if (cancelled) {
mCancellingTask = mTask;
cancelLoadInBackground();
}
mTask = null;
return cancelled;
}
}
return false;
}
//dispatchOnCancelled 或者在 dispatchOnLoadComplete 是判断是 abandon 了。
public void onCanceled(D data) {}
void executePendingTask() {
if (mCancellingTask == null && mTask != null) {
//若是mTask正在等待被执行。
if (mTask.waiting) {
mTask.waiting = false; //那么把它从队列中移除。
mHandler.removeCallbacks(mTask);
}
if (mUpdateThrottle > 0) {
long now = SystemClock.uptimeMillis();
if (now < (mLastLoadCompleteTime+mUpdateThrottle)) {
//放入等待队列当中。
mTask.waiting = true;
mHandler.postAtTime(mTask, mLastLoadCompleteTime+mUpdateThrottle);
return;
}
}
//执行这个任务。
mTask.executeOnExecutor(mExecutor, (Void[]) null);
}
}
void dispatchOnCancelled(LoadTask task, D data) {
onCanceled(data); //回调onCanceled.
if (mCancellingTask == task) { //若是被取消的task执行完了。
rollbackContentChanged();
mLastLoadCompleteTime = SystemClock.uptimeMillis();
mCancellingTask = null;
deliverCancellation(); //经过被取消的task执行完了。
executePendingTask(); //执行当前的Task。
}
}
void dispatchOnLoadComplete(LoadTask task, D data) {
if (mTask != task) { //若是执行完的task不是最新的。
dispatchOnCancelled(task, data);
} else {
if (isAbandoned()) { //若是被abandon了。
onCanceled(data);
} else {
commitContentChanged();
mLastLoadCompleteTime = SystemClock.uptimeMillis();
mTask = null;
deliverResult(data);
}
}
}
public abstract D loadInBackground();
//mTask在后台执行时回调这个方法。
protected D onLoadInBackground() {
return loadInBackground();
}
//mTask在执行过程当中被经过cancelLoad()取消了。
public void cancelLoadInBackground() {}
public boolean isLoadInBackgroundCanceled() {
return mCancellingTask != null;
}
public void waitForLoader() {
LoadTask task = mTask;
if (task != null) {
task.waitForLoader();
}
}
}
复制代码
Loader
关于如何实现AsyncTaskLoader
,系统提供了一个很好的例子,那就是CursorLoader
,它用来读取ContentProvider
中的数据,并支持传入关于查询的projection/selection/selectionArgs
等条件,最终返回一个cursor
,在返回以后负责cursor
的关闭。 为了更加灵活,咱们参照它的写法,抽象出其中的关键代码,让使用者最多只须要负责两样东西:ui
BaseLoader
的实现者只须要关注下面这三个方法:this
//异步加载数据,这个Bundle就是onCreateLoader时传入的Bundle,咱们能够把查询的关键词放在其中,这个是子类必须实现的方法。
protected abstract Result loadData(Bundle bundle);
//下面两个方法是用于结果资源的回收,例如cursor的关闭,当咱们的返回值只是一些基本数据类型时,并不须要实现它。
protected void releaseResult(Result result) {}
protected boolean isResultReleased(Result result) { return true; }
复制代码
下面是所有的实现代码:spa
public abstract class BaseDataLoader<Result> extends AsyncTaskLoader<Result> {
Result mResult;
Bundle mBundles;
CancellationSignal mCancellationSignal;
//全部的子类最多只须要实现下面的三个方法,而不要回收资源的只用实现loadData就能够了。
protected abstract Result loadData(Bundle bundle);
protected void releaseResult(Result result) {}
protected boolean isResultReleased(Result result) { return true; }
public BaseDataLoader(Context context, Bundle bundle) {
super(context);
mBundles = bundle;
}
@Override
public Result loadInBackground() {
synchronized (this) {
if (isLoadInBackgroundCanceled()) {
throw new OperationCanceledException();
}
mCancellationSignal = new CancellationSignal();
}
try {
return loadData(mBundles);
} finally {
synchronized (this) {
mCancellationSignal = null;
}
}
}
@Override
public void cancelLoadInBackground() {
super.cancelLoadInBackground();
synchronized (this) {
if (mCancellationSignal != null) {
mCancellationSignal.cancel();
}
}
}
@Override
public void deliverResult(Result result) {
if (isReset()) {
if (result != null && !isResultReleased(result)) {
releaseResult(result);
}
return;
}
Result oldResult = mResult;
mResult = result;
if (isStarted()) {
super.deliverResult(result);
}
if (oldResult != null && oldResult != result && !isResultReleased(oldResult)) {
releaseResult(oldResult);
}
}
@Override
protected void onStartLoading() {
if (mResult != null) {
deliverResult(mResult);
}
if (takeContentChanged() || mResult == null) {
forceLoad();
}
}
@Override
protected void onStopLoading() {
cancelLoad();
}
@Override
public void onCanceled(Result result) {
if (result != null && !isResultReleased(result)) {
releaseResult(result);
}
}
@Override
protected void onReset() {
super.onReset();
onStopLoading();
if (mResult != null && !isResultReleased(mResult)) {
releaseResult(mResult);
}
mResult = null;
}
}
复制代码