Loader是官方提供的一个类,顾名思义,Loader的作用是加载数据。
和Activity类似,Loader提供了6个生命周期,从方法的名字很容易区分它们的作用。
- startLoading
- cancelLoad
- forceLoad
- stopLoading
- abandon
- reset
public class Loader<D> {
@MainThread
public final void startLoading() {
mStarted = true;
mReset = false;
mAbandoned = false;
onStartLoading();
}
@MainThread
protected void onStartLoading() {
}
public boolean isStarted() {
return mStarted;
}
@MainThread
public boolean cancelLoad() {
return onCancelLoad();
}
@MainThread
protected boolean onCancelLoad() {
return false;
}
@MainThread
public void forceLoad() {
onForceLoad();
}
@MainThread
protected void onForceLoad() {
}
@MainThread
public void stopLoading() {
mStarted = false;
onStopLoading();
}
@MainThread
protected void onStopLoading() {
}
@MainThread
public void abandon() {
mAbandoned = true;
onAbandon();
}
@MainThread
protected void onAbandon() {
}
public boolean isAbandoned() {
return mAbandoned;
}
@MainThread
public void reset() {
onReset();
mReset = true;
mStarted = false;
mAbandoned = false;
mContentChanged = false;
mProcessingChange = false;
}
@MainThread
protected void onReset() {
}
public boolean isReset() {
return mReset;
}
@MainThread
public void deliverCancellation() {
if (mOnLoadCanceledListener != null) {
mOnLoadCanceledListener.onLoadCanceled(this);
}
}
@MainThread
public void deliverResult(@Nullable D data) {
if (mListener != null) {
mListener.onLoadComplete(this, data);
}
}
}
开发者不必直接使用Loader,通过LoaderManager调用,LoaderManager的作用是绑定和管理Activity与Loader的生命周期,避免内存泄露。
通过LoaderManager的静态方法getInstance获取LoaderManager实例:
@NonNull
public static <T extends LifecycleOwner & ViewModelStoreOwner> LoaderManager getInstance(
@NonNull T owner) {
return new LoaderManagerImpl(owner, owner.getViewModelStore());
}
然后调用initLoader
@MainThread
@NonNull
public abstract <D> Loader<D> initLoader(int id, @Nullable Bundle args,
@NonNull LoaderManager.LoaderCallbacks<D> callback);
第三个参数LoaderManager.LoaderCallbacks<D> callback
是一个回调,在回调中,开发者处理Loader的创建等工作。
public interface LoaderCallbacks<D> {
@MainThread
@NonNull
Loader<D> onCreateLoader(int id, @Nullable Bundle args);
@MainThread
void onLoadFinished(@NonNull Loader<D> loader, D data);
@MainThread
void onLoaderReset(@NonNull Loader<D> loader);
}
如何创建Loader?
开发者需要通过继承Loader,在相应的生命周期中处理自己的逻辑。同时,官方提供了2个子类,AsyncTaskLoader
和CursorLoader
,AsyncTaskLoader是异步加载的实现,CursorLoader继承自AsyncTaskLoader,在异步代码中使用ContentResolver
加载数据。
我们并没有调用开始方法,LoaderManager是这么做到自动加载的呢?
LoaderManagerImpl是LoaderManager的实现类,实际上我们调用getInstance时,返回的实例正是LoaderManagerImpl
当我们调用initLoader时:
class LoaderManagerImpl extends LoaderManager {
@MainThread
@NonNull
@Override
public <D> Loader<D> initLoader(int id, @Nullable Bundle args,
@NonNull LoaderCallbacks<D> callback) {
LoaderInfo<D> info = mLoaderViewModel.getLoader(id);
if (info == null) {
return createAndInstallLoader(id, args, callback, null);
} else {
return info.setCallback(mLifecycleOwner, callback);
}
}
}
没有缓存的LoaderInfo,会进入创建逻辑:
@MainThread
@NonNull
private <D> Loader<D> createAndInstallLoader(int id, @Nullable Bundle args,
@NonNull LoaderCallbacks<D> callback, @Nullable Loader<D> priorLoader) {
LoaderInfo<D> info;
try {
mLoaderViewModel.startCreatingLoader();
Loader<D> loader = callback.onCreateLoader(id, args);
info = new LoaderInfo<>(id, args, loader, priorLoader);
mLoaderViewModel.putLoader(id, info);
} finally {
mLoaderViewModel.finishCreatingLoader();
}
return info.setCallback(mLifecycleOwner, callback);
}
LoaderInfo继承自MutableLiveData,到这一步,我们就知道答案了,在LoaderInfo的onActive方法中,见到了Loader的身影,onActive则是Activity对用户可见时,被调用的。
public static class LoaderInfo<D> extends MutableLiveData<D>
implements Loader.OnLoadCompleteListener<D> {
private final @NonNull Loader<D> mLoader;
LoaderInfo(int id, @Nullable Bundle args, @NonNull Loader<D> loader,
@Nullable Loader<D> priorLoader) {
mLoader = loader;
}
@Override
protected void onActive() {
mLoader.startLoading();
}
@Override
protected void onInactive() {
mLoader.stopLoading();
}
}
同时,在onInactive
方法中,调用了mLoader.stopLoading()
。因此,开发过程中,我们只需要关注LoaderCallbacks
的方法即可。
AsyncTaskLoader的实现
AsyncTaskLoader是Loader的异步实现。
梳理前,需要先看一下CursorLoader,前面已经知道,界面出现后会调用Loader.startLoading(),在
@MainThread
public final void startLoading() {
mStarted = true;
mReset = false;
mAbandoned = false;
onStartLoading();
}
然后进入onStartLoading,CursorLoader复写了这个方法:
@Override
protected void onStartLoading() {
if (takeContentChanged() || mCursor == null) {
forceLoad();
}
}
然后进入forceLoad:
@MainThread
public void forceLoad() {
onForceLoad();
}
CursorLoader没有复写onForceLoad方法,其父类AsyncTaskLoader中复写了该方法,自此逻辑正式进入AsyncTaskLoader:
public abstract class AsyncTaskLoader<D> extends Loader<D> {
@Override
protected void onForceLoad() {
super.onForceLoad();
cancelLoad();
mTask = new LoadTask();
executePendingTask();
}
}
executePendingTask内我们看到了熟悉的线程池操作
void executePendingTask() {
if (mCancellingTask == null && mTask != null) {
mTask.executeOnExecutor(mExecutor, (Void[]) null);
}
}
mTask是一个LoadTask实例,LoadTask继承自ModernAsyncTask:
abstract class ModernAsyncTask<Params, Progress, Result> {
public final ModernAsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
}
mWorker和mFuture的初始化位于构造方法中:
ModernAsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
@Override
public Result call() throws Exception {
Result result = null;
try {
result = doInBackground(mParams);
} finally {
postResult(result);
}
return result;
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
final Result result = get();
postResultIfNotInvoked(result);
}
};
}
实例化mWorker的匿名内部类中,调用了doInBackground。子类LoadTask实现了doInBackground:
final class LoadTask extends ModernAsyncTask<Void, Void, D> implements Runnable {
@Override
protected D doInBackground(Void... params) {
try {
D data = AsyncTaskLoader.this.onLoadInBackground();
return data;
} catch (OperationCanceledException ex) {
return null;
}
}
}
至此,我们就完成了AsyncTaskLoader实现异步的流程梳理。
public abstract class AsyncTaskLoader<D> extends Loader<D> {
@Nullable
protected D onLoadInBackground() {
return loadInBackground();
}
@Nullable
public abstract D loadInBackground();
}
CursorLoader的实现
熟悉了AsyncTaskLoader的流程,CursorLoader的流程就简单了很多。
public class CursorLoader extends AsyncTaskLoader<Cursor> {
@Override
public Cursor loadInBackground() {
synchronized (this) {
mCancellationSignal = new CancellationSignal();
}
try {
Cursor cursor = ContentResolverCompat.query(getContext().getContentResolver(),
mUri, mProjection, mSelection, mSelectionArgs, mSortOrder,
mCancellationSignal);
if (cursor != null) {
try {
cursor.getCount();
cursor.registerContentObserver(mObserver);
} catch (RuntimeException ex) {
cursor.close();
throw ex;
}
}
return cursor;
} finally {
synchronized (this) {
mCancellationSignal = null;
}
}
}
}
总结:
- Loader的生命周期方法的定义非常有规律:
- startLoading是用final修饰的,代表子类无法复写修改其中的逻辑
- 非on开头的方法都是用public修饰的,表示可以被外部调用,而on开头的方法都是protected修饰,无法被外部调用;非on开头的方法,内部都调用了对应的on方法。由此我们可以总结:非on方法主要用于Loader外部,on方法用于Loader内部,两者在Loader内部组合在一起。
- 每个生命周期,都有对应的is方法
- 考虑到Loader操作主要是异步的,因此使用LoaderManager管理Loader生命周期,避免内存泄漏。使用MutableLiveData监听Acitivty生命周期。
参考资料:
LoaderManager API