Foreword
AsyncTask
, HandlerThrad
, IntentService
Are on the Android messaging packages and applications, solve the problem child thread time-consuming task, the main thread to update the UI.
AsyncTask use
AsyncTask is an abstract class, subclass inherits by rewriting doInBackground
, which runs a sub-thread.
public class DownloadTask extends AsyncTask<String,Integer,String> {
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
@Override
protected String doInBackground(String... strings) {
publishProgress(1);
return "AsyncTask";
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
}
复制代码
AsyncTask<Params, Progress, Result>
Generic parameters, according to business needs, pass different types. The first parameter Params
refers to passed doInBackground
URL parameter type, such as blind ah schedule. The second parameter Progress
refers to the execution doInBackground
time of the method, the publishProgress
progress of the state of progress of update type, such as downloaded. The third parameter Result
is doInBackground
the end of the process performs spread onPostExecute
parameter types, such as downloading results.
Related Methods
- onPreExecute()
The main thread. Before you can begin the task of UI data or preliminary preparation. Non-essential method.
- doInBackground
(Thread pool) to run the child thread. Generally time-consuming operation, such download. AsyncTask abstract method, and must be implemented.
- onProgressUpdate
The main thread, call publishProgress callback method will be the method doInBackground method, it displays the current task status. Used to update the download progress. Non-essential method.
- onPostExecute
The main thread. After return value doInBackground method, the callback method. Non-essential method.
- onCancelled
When the main thread running, the task completion callback method, indicating the end of the task.
Start Task
execute the task can only be called once, otherwise an error.
DownloadTask task=new DownloadTask();
task.execute("Git");
复制代码
Source code analysis
AsyncTask constructor
Android is in code comments must be called on the UI thread, the UI thread because the default has Looper, and AsyncTask needs to be updated UI. If you do not update the UI, can be created in the child thread has Looper.
//构造方法1
public AsyncTask() {
this((Looper) null);
}
//构造方法2
public AsyncTask(@Nullable Handler handler) {
this(handler != null ? handler.getLooper() : null);
}
//构造方法3
public AsyncTask(@Nullable Looper callbackLooper) {
分析一:
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
分析二:
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
postResult(result);
}
return result;
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
复制代码
Constructor 1,2, 3 finally call the constructor. Look constructor 3 did what?
Analysis of a
MHanlder assignment to initialize. Looper first determine whether the incoming objects, if not passed, or passed Looper Looper and objects and the UI thread of the same, by calling the getMainHandler
calling method Handler object UI thread (here can be simply understood, AsyncTask created in the UI thread). If not equal, new
a Handler
target.
//AsyncTask
private static Handler getMainHandler() {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler(Looper.getMainLooper());
}
return sHandler;
}
}
//Looper
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
复制代码
AsyncTask the getMainHandler
method, by calling the Looper getMainLooper
to get Looper objects (UI thread Looper Object) method and create InternalHandler. Here you can see that in the absence of incoming Looper, and does not create AsyncTask the UI thread, Looper will get less than the object. sHandler variable is InternalHandler types, inheritance Handler.
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
复制代码
In the method of treatment, you can see is MESSAGE_POST_RESULT
the message and MESSAGE_POST_PROGRESS
process messages, used at the end of the mission and progress updates, switch to the main thread, the callback related methods.
Analysis II
Static abstract class WorkerRunnable inherit Callable, more than just add an array mParams, for saving parameters. In WorkerRunnable's call
approach, calling our major rewrite doInBackground
. The final call to postResult
the method.
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
复制代码
In a analysis, the final processing of the objects seen InternalHandler MESSAGE_POST_RESULT message, call AsyncTask object's finish
methods.
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
复制代码
According to the current state of the call AsyncTask onCancelled
or onPostExecute
method.
In the configuration of AsyncTask method. By constructing Handler object, and construction WorkRunnable objects and objects used to create WorkRunnable FutureTask objects. FutureTask realized RunnableFuture interface, and RunnableFuture interface extends Runnable interface and Future interfaces. Therefore, not only do FutureTask is a Runnable Thread object directly executed, but also as a calculation result obtained for Future object of Callable.
AsyncTask execution
DownloadTask task=new DownloadTask();
task.execute("Git");
复制代码
We create DownloadTask objects in the UI thread, and calling DownloadTask object's execute
method, Git
the method that we want to spread doInBackground
the value of the method;
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
复制代码
AsyncTask call the execute方
method calls executeOnExecutor
methods.
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
复制代码
If the current AsyncTask running object or end, will throw an exception, a task can only be run once. Here called onPreExecute
method and parameters assigned to the variable WorkerRunable omParams object mentioned earlier. Executed by a thread pool object exex FutureTask object constructor to create the final call to WorkerRunable object call
methods to execute our overridden doInBackground
method.
Here we take a look at the thread pool object sDefaultExecutor.
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
复制代码
The class constructor SerialExecutor
private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive;
public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}
复制代码
By ArrayDequ save the task, and locking mechanism to execute synchronization method, serial tasks.
THREAD_POOL_EXECUTO
What stuff?
public static final Executor THREAD_POOL_EXECUTOR;
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;
复制代码
Unsurprisingly is a thread pool.
to sum up
By tracking AsyncTask constructor, we understand the whole process of implementation AsyncTask. Looper Handler object created by an object, for transmitting a message in the thread pool, switching to the UI thread, related operations. And create WorkRunnable object calls a background task (we rewrite the doInBackground
method), the WorkRunnable FutureTask object to the object so that when the thread pool, the results and process control.
In AsyncTask the execute
way to track, we know the background task queue holds two-way, lock the thread pool by a synchronous serial operation.
Also note that, AsyncTask Activity life cycle and life cycle are not the same, if AsyncTask holds Activity, likely to cause a memory leak. Similarly Download consuming operation is recommended IntentServcie
.
Sharing knowledge