【Android】Loader及LoaderManager的使用和源码分析

Loader是官方提供的一个类,顾名思义,Loader的作用是加载数据。
和Activity类似,Loader提供了6个生命周期,从方法的名字很容易区分它们的作用。

  1. startLoading
  2. cancelLoad
  3. forceLoad
  4. stopLoading
  5. abandon
  6. 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个子类,AsyncTaskLoaderCursorLoader,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;
            }
        }
    }
}

总结:

  1. Loader的生命周期方法的定义非常有规律:
  • startLoading是用final修饰的,代表子类无法复写修改其中的逻辑
  • 非on开头的方法都是用public修饰的,表示可以被外部调用,而on开头的方法都是protected修饰,无法被外部调用;非on开头的方法,内部都调用了对应的on方法。由此我们可以总结:非on方法主要用于Loader外部,on方法用于Loader内部,两者在Loader内部组合在一起。
  • 每个生命周期,都有对应的is方法
  1. 考虑到Loader操作主要是异步的,因此使用LoaderManager管理Loader生命周期,避免内存泄漏。使用MutableLiveData监听Acitivty生命周期。

参考资料:
LoaderManager API

猜你喜欢

转载自blog.csdn.net/qq_23049111/article/details/126622379
今日推荐