
关于AsyncTaskLoader
Concurrency基础H1
ExecutorH2
Executor是一个用来执行Runable实例的对象,接口定义如下
bash
/*** An object that executes submitted {@link Runnable} tasks. This* interface provides a way of decoupling task submission from the* mechanics of how each task will be run, including details of thread* use, scheduling, etc. An {@code Executor} is normally used* instead of explicitly creating threads.*/public interface Executor {/*** Executes the given command at some time in the future. The command* may execute in a new thread, in a pooled thread, or in the calling* thread, at the discretion of the {@code Executor} implementation.** @param command the runnable task* @throws RejectedExecutionException if this task cannot be* accepted for execution* @throws NullPointerException if command is null*/void execute(Runnable command);}
ExecutorServiceH2
ExecutorService继承自Executor,也是用来执行Runable对象的,但是额外提供了方法能够返回Future对象用来跟踪异步任务的状态
ThreadPoolExecutor、ScheduledThreadPoolExecutorH2
都是ExecutorService的实现类,ScheduledThreadPoolExecutor继承自ThreadPoolExecutor,提供了重复执行异步任务的功能
ExecutorsH2
ExecutorService、Callable等的工厂类工具了,提供了一些方法返回各种ExecutorService的实例类,以及可以把Runnable转换成Callable实例
RunnableH2
Runnable代表可执行线程的单元。
bash
public class SimpleTask implements Runnable{@Overridepublic void run() {System.out.println("SimpleTask, Runnable: Executing Logic");}}public class Client {/*** @param args*/public static void main(String[] args) {// Step1 : Create a RunnableRunnable simpleTask = new SimpleTask();// Step 2: Configure Executor// Uses FixedThreadPool executorExecutorService executor = Executors.newFixedThreadPool(2);executor.submit(simpleTask);executor.shutdown();}}
CallableH2
和Runnable类似,但是它可以返回值、抛出异常
bash
public class CallableTask implements Callable<String>{@Overridepublic String call() throws Exception {String s="Callable Task Run at "+System.currentTimeMillis();return s;}}public class CallableClient {/*** @param args*/public static void main(String[] args) {// Step1 : Create a RunnableCallable callableTask = new CallableTask();// Step 2: Configure Executor// Uses FixedThreadPool executorExecutorService executor = Executors.newFixedThreadPool(2);Future<String> future = executor.submit(callableTask);boolean listen = true;while (listen) {if (future.isDone()) {String result;try {result = future.get();listen = false;System.out.println(result);} catch (InterruptedException | ExecutionException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}
FutureH2
代表一个异步执行的结果。可以用来查询最终的执行结果以及查询异步任务的状态
FutureTaskH2
实现一个可以取消的异步执行。它实现了Runnable和Future接口,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。
Android LoaderH1
AsyncTaskH2
AsyncTask提供一个更为简单的方式使用UI线程的机制,它允许我们在其他线程执行后台操作,最终把执行结果push回UI线程。
需要在后台执行的逻辑需要实现在doInBackground方法,最终执行这个AsyncTask需要调用execute方法。
AsyncTask会在初始化的时候实例化一个实现了Runnable接口的WorkerRunnable,在它的call方法的逻辑中主要调用了需要子类实现的doInBackground方法:
bash
mWorker = new WorkerRunnable<Params, Result>() {public Result call() throws Exception {mTaskInvoked.set(true);Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);//noinspection uncheckedreturn postResult(doInBackground(mParams));}};
同时还会初始化一个FutureTask对象实例:
bash
mFuture = new FutureTask<Result>(mWorker) {@Overrideprotected void done() {try {postResultIfNotInvoked(get());} catch (InterruptedException e) {android.util.Log.w(LOG_TAG, e);} catch (ExecutionException e) {throw new RuntimeException("An error occured while executing doInBackground()",e.getCause());} catch (CancellationException e) {postResultIfNotInvoked(null);}}};
最终调用execute方法的时候就会执行上述的FutureTask实例
ModernAsyncTaskH2
ModernAsyncTask是AsyncTask的一个拷贝,它仅仅包括了用来支持AsyncTaskLoader的代码,因为它需要其中一部分的功能。
AsyncTaskLoaderH2
AsyncTaskLoader继承子Loader,主要用来通过异步任务来加载数据。所以它内部有一个继承自ModernAsyncTask的内部类LoadTask的成员变量,AsyncTaskLoader最终的异步执行都是代理给这个成员变量来执行的。
bash
final class LoadTask extends ModernAsyncTask<Void, Void, D> implements Runnable {D result;boolean waiting;private CountDownLatch done = new CountDownLatch(1);/* Runs on a worker thread */@Overrideprotected D doInBackground(Void... params) {if (DEBUG) Log.v(TAG, this + " >>> doInBackground");result = AsyncTaskLoader.this.onLoadInBackground();if (DEBUG) Log.v(TAG, this + " <<< doInBackground");return result;}/* Runs on the UI thread */@Overrideprotected void onPostExecute(D data) {if (DEBUG) Log.v(TAG, this + " onPostExecute");try {AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);} finally {done.countDown();}}@Overrideprotected void onCancelled() {if (DEBUG) Log.v(TAG, this + " onCancelled");try {AsyncTaskLoader.this.dispatchOnCancelled(this, result);} finally {done.countDown();}}@Overridepublic void run() {waiting = false;AsyncTaskLoader.this.executePendingTask();}}
可以看到LoadTask还实现了Runnable接口,并且在实现逻辑中调用了AsyncTaskLoader的executePendingTask方法。
executePendingTask最终则会执行这个LoadTask的异步代码:
bash
void executePendingTask() {if (mCancellingTask == null && mTask != null) {if (mTask.waiting) {mTask.waiting = false;mHandler.removeCallbacks(mTask);}if (mUpdateThrottle > 0) {long now = SystemClock.uptimeMillis();if (now < (mLastLoadCompleteTime+mUpdateThrottle)) {// Not yet time to do another load.if (DEBUG) Log.v(TAG, "Waiting until "+ (mLastLoadCompleteTime+mUpdateThrottle)+ " to execute: " + mTask);mTask.waiting = true;mHandler.postAtTime(mTask, mLastLoadCompleteTime+mUpdateThrottle);return;}}if (DEBUG) Log.v(TAG, "Executing: " + mTask);mTask.executeOnExecutor(ModernAsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);}}
除了Runnable接口之外,forceLoad方法也调用了executePendingTask会执行实际的异步任务。而且实际我也发现这个Runnable对象也没有在另外的线程中执行。
所以我们的实现了LoaderCallbacks#onCreateLoader的方法后会发现,Loader并没有执行,而是要调用forceLoad方法才会执行。当然更合理的是把调用移到onStartLoading中:
bash
@Overrideprotected void onStartLoading() {if (data != null)deliverResult(data);if (takeContentChanged() || data == null)forceLoad();}
其他的一些问题H1
forceLoad的问题H2
每次Loader开始执行后,在执行完成deliverResult之前,如果再次执行forceLoad,那么上一次直接结果最终并不会执行onLoadFinished方法。原因如下:
上面的分析看到LoadTask的onPostExecute会调用AsyncTaskLoader的dispatchOnLoadComplete方法:
bash
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 {mLastLoadCompleteTime = SystemClock.uptimeMillis();mTask = null;if (DEBUG) Log.v(TAG, "Delivering result");deliverResult(data);}}}
而AsyncTaskLoader的onForceLoader方法又是会重新创建LoadTask的实例
bash
@Overrideprotected void onForceLoad() {super.onForceLoad();cancelLoad();mTask = new LoadTask();if (DEBUG) Log.v(TAG, "Preparing load: mTask=" + mTask);executePendingTask();}
所以最终的执行结果并不会传递到LoaderManager中。
评论
新的评论
上一篇
FLAG_ACTIVITY_CLEAR_TOP launches new instance
错误 在使用 NavUtils.navigateUpFromSameTask(this) 导航到父Activity时,页面切换的动画是从右往左滑动,这样的动画看起来不像是返回动画,而是打开了一个新的页面的动画。 原因 SDK版本小于16时, NavUtilsImpl 的实现是 …
下一篇
使用springfox生成springmvc项目的swagger的文档
介绍 Swagger Swagger 是用来描述和文档化RESTful API的一个项目。 Swagger Spec 是一套规范,定义了该如何去描述一个 RESTful API 。类似的项目还有 RAML 、 API Blueprint 。 根据 Swagger Spec 来描…
