线程
线程是操作系统调度的最小单元,在android中,主线程又称为UI线程,执行的是与界面渲染等操作,
而工作线程一般承担耗时多的操作。
Android中线程的实现方式有以下几种:
1.AsyncTask 线程池
2.IntentService 线程
3.HandlerThread 线程
AsyncTask
android 1.6 前串行
1.6-3.0 并行
3.0后串行,引入excuteOnExecutor可以进行并行操作
实例化与execute都是只能在主线程进行的
1)execute操作会调用onPreExecute操作
2)静态成员会在加载类时进行初始化,否则同一进程中的AsyncTask都将无法正常工作
工作原理:
asyncTask中有两个主要的线程池,分别是
THREAD_POOL_EXECUTOR
这个线程池抓哟是跟具体的任务执行相关,其实例是ThreadPoolExecutor
SERIAL_EXECUTOR
充当串行任务排队的作用,如果是自己调用excuteOnExecutor,则调度方式由自己传入的线程池决定
mWorker (WorkerRunnable) 用于执行相关的任务
mFuture (FutrueTask) 用于完成结果回调使用,发送相关的信息,告知handler结束
sHandler (InternalHandler) 实现的关键角色,创建于主线程中,且负责接受相关的回调信息并处理
private static class InternalHandler extends Handler {
public InternalHandler() {
//注意这里是主线程中的,保证处理信息的时候是在主线程中进行
super(Looper.getMainLooper());
}
@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;
}
}
}
1.实例化时,会准备好mWorker 和 mFuture,这两个相当于回调函数
2.调用excute函数会调用到excuteOnExecutor,此时会调用onPreExecute(),并会交给调度的线程池去调度任务,提取到的任务再交给指定的线程池去执行任务,默认采用THREAD_POOL_EXECUTOR,串行线程池,此时传入了(mFuture),而mFutrue已传入mWorker的参数,能够回调mWorker的 call方法
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(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);
}
}
};
3.在call方法中会调用doInBackground方法,此时,其实此方法其实已经在已开辟的线程池中执行了。
4.执行完,通过postResult让信息发送给sHandler,再回调onPostExecute 完成整个过程。
总之,巧妙使用了线程池的回调runnable,再通过handler,message实现主,工作线程的消息传递。
这里的handler是主线程下的handler,这主要是保证回调能够直接操纵UI元素。
HandlerThread
是继承自Thread的类,自动帮我们创建好looper,这样创建handler就不用手动Looper初始化了
ps:可以理解为,集合了looper的thread
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
其调用主要实现如下:
mHandlerThread = new HandlerThread("MyHandler");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper(), new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
return false;
}
});
mHandler.post(new Runnable() {
public void run() {
//任务1
mHandler.sendMessage();
//任务2
}
});
这样,就能够直接在run中执行相关任务。
需要注意的是,初始化后该Thread是无限循环的,需要手动终止线程执行,即调用quitSafely或者quit
IntentService
继承于Service的一个自带工作线程的Service=。=优先级还是蛮高的呢
其实现主要依靠handlerThread进行的,onCreate中实例化handlerThread,onStart中发送消息,
然后在handlerMessage过程中调用onHandlerIntent,完成工作线程的任务,完成后直接结束=。=
值得注意的是,退出调用的是stopSelf(int startId); 这会检查是否有新的消息入列,这对于多次派发任务是有帮助的,不至于那么快结束。