Android中异步处理技术
Android应用中各种类型的线程本质上都基于Linux系统的pthreads,在应用层可以分为三种类型的线程
1.主线程:又叫UI线程,此线程非线程安全,所以在应用更新UI的时候需要使用Handler发送消息到主线程更新。
2.Binder线程:解决进程与进程之间的通信问题。每个进程都维护了一个线程池,用来处理其它进程中线程发送的消息。一个比较典型的使用场景是应用提供一个给其它进程通过AIDL接口绑定的Service。
3.后台线程:在应用中显式创建的线程都是后台线程,也就是说需要手动添加任务的线程,在Linux系统层面UI线程和后台线程其实是一样的。在Android框架中,通过WindowManager赋予了主线程只能处理UI更新以及后台线程不能直接操作UI的限制。
主要实现方式有以下几种
1.Thread Runnable java 中的线程机制
2.HandlerThread 是集成了Looper和MessageQueue源码如下
public void run(){
...
looper.prepare();
synchronized(this){
mLooper = Looper.myLooper();
notifyAll();
}
looper.loop();
}
looper.prepare() 生成了一个looper对象,mLooper = Looper.myLooper() 获取到刚刚生成的looper对象使用。使用方法如下
HandlerThread handlerThread = new HandlerThread("HandlerThread");
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper()){
@Override
public void handleMessage(Message msg)[
super.handleMessage(msg)
}
}
handlerThread.getLooper() 是阻塞的只有当HandlerThread start()后才回继续执行,否则一直阻塞。所以要先开启再调用。
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
3.IntentService
Service 的各个生命周期函数都是运行在主线程的,因此它本身并不是一个一步处理技术,为了能够在Service中实现子线程中处理耗时任务,Android引入了一个Service的子类:IntentService。IntentService具有和Service一样的生命周期,同时也提供了在后台线程中处理异步任务的机制。IntentService 也是在后台线程中执行所有的任务,我们通过给Context.startService传递一个Intent类型的参数可以启动IntentService,如果此时有任务正在执行,则这个Intent将会进入队列进行排队,如果没有任务,那么将会启动一个新的IntentService,当所有任务结束完成之后,IntentService将会自动结束它的生命周期。
4.AsyncTask
部分源码如下
private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
return postResult(doInBackground(mParams));
}
};
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 occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
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;
}
可以看出它的内部实现了一个Callable<T>的接口。然后放入FutureTask中,并
监听它的done()方法,一旦外部调用execute()方法,这个FutureTask对象就被放入线程池当中。等待执行完毕,done()会被回调,并通过Handler发送消息给主线程来更新UI。
5.Loader Android3.0 引入的异步数据加载框架,其实就是对AsyncTask进行了MVP设计模式的封装,使得异步数据加载更加容易实现和维护,结构更加清晰。如果大家有兴趣可以去看源码或者看这篇博客,讲的已经挺清楚的了。
http://www.jianshu.com/p/385327e35711