Android组件与进程,进程的优先级,组件都在主线程,线程安全等。
提到android的多线程,必须提下特有的异步task类,AsyncTask。
AsyncTask 的优势体现在:
线程无法管理,匿名线程创建并启动后就不受程序的控制了,如果有很多个请求发送,那么就会启动非常多的线程,系统将不堪重负。
代码更简洁,实现起来更方便。
AsyncTask的本质是一个线程池,所有提交的异步任务都会在这个线程池中的工作线程内执行,当工作线程需要跟UI线程交互时,工作线程会通过向在UI线程创建的Handler传递消息的方式,调用相关的回调函数,从而实现UI界面的更新。
成员变量:
private static final int CORE_POOL_SIZE = 5;//5个核心工作线程
private static final int MAXIMUM_POOL_SIZE = 128;//最多128
private static final int KEEP_ALIVE = 1;//空闲线程超时时间1s
private static final BlockingQueue<Runnable> sWorkQueue =
new LinkedBlockingQueue<Runnable>(10);//等待队列
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
}
};//线程工厂
private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);//自定义线程池
private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;
private static final int MESSAGE_POST_CANCEL = 0x3;
private static final InternalHandler sHandler = new InternalHandler();//内部的handler
构造方法,注意这个初始化一定要在UI线程中进行:
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return doInBackground(mParams);
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
Message message;
Result result = null;
try {
result = 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) {
message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));
message.sendToTarget();//取消任务
return;
} catch (Throwable t) {
throw new RuntimeException("An error occured while executing "
+ "doInBackground()", t);
}
message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(AsyncTask.this, result));
message.sendToTarget();//成功,发送message
}
};
}
WorkerRunnable类实现了callable接口的call()方法,该函数会调用我们在AsyncTask子类中实现的doInBackground(mParams)方法,由此可见,WorkerRunnable封装了我们要执行的异步任务。FutureTask中的protected void done() {}方法实现了异步任务状态改变后的操作。当异步任务被取消,会向UI线程传递MESSAGE_POST_CANCEL消息,当任务成功执行,会向UI线程传递MESSAGE_POST_RESULT消息,并把执行结果传递到UI线程。
下面是AsyncTask的execute(Params...params)方法
public final AsyncTask<Params,Progress, Result> execute(Params... params) {
if (mStatus != Status.PENDING) {//Status有PENDING(未执行),RUNNING(正在执行),FINISHED(已完成)三个状态,如果mStatus不为PENDING,则抛出异常
switch (mStatus) {
case RUNNING:
throw newIllegalStateException("Cannot execute task:"
+ " the taskis already running.");
case FINISHED:
throw newIllegalStateException("Cannot execute task:"
+ " the taskhas already been executed "
+ "(a task canbe executed only once)");
}
}
mStatus = Status.RUNNING;
onPreExecute();//运行在ui线程,在提交任务到线程池之前执行
mWorker.mParams = params;
sExecutor.execute(mFuture);//提交任务到线程池
return this;
}
当任务正在执行或者已经完成,会抛出IllegalStateException,由此可知我们不能够重复调用execute(Params...params)方法。在提交任务到线程池之前,调用了onPreExecute()方法。然后才执行sExecutor.execute(mFuture)是任务提交到线程池。
当任务的状态发生改变时(1、执行成功2、取消执行3、进度更新),工作线程会向UI线程的Handler传递消息。Handler要处理其他线程传递过来的消息。在AsyncTask中,InternalHandler是在UI线程上创建的,它接收来自工作线程的消息,实现代码如下:
private static class InternalHandler extends Handler {
@SuppressWarnings({"unchecked","RawUseOfParameterizedType"})
@Override
public voidhandleMessage(Message msg) {
AsyncTaskResult result =(AsyncTaskResult) msg.obj;
switch (msg.what) {
caseMESSAGE_POST_RESULT:
// There is onlyone result
result.mTask.finish(result.mData[0]);//执行任务成功
break;
caseMESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);//进度更新
break;
caseMESSAGE_POST_CANCEL:
result.mTask.onCancelled();//取消任务
break;
}
}
}
当接收到消息之后,AsyncTask会调用自身相应的回调方法。
总结:
1、 AsyncTask的本质是一个静态的线程池,AsyncTask派生出的子类可以实现不同的异步任务,这些任务都是提交到静态的线程池中执行。
2、线程池中的工作线程执行doInBackground(mParams)方法执行异步任务
3、当任务状态改变之后,工作线程会向UI线程发送消息,AsyncTask内部的InternalHandler响应这些消息,并调用相关的回调函数
4,AsyncTask在Activity因为OnConfiguration重绘时要注意。