多线程
- AsyncTask, HandlerThread, IntentService ,ThreadPool, Loader等
一 AsyncTask
- 内部是Thread+Handler。
- Android1.5 前,AsyncTask执行时顺序的,需要等待上一个task执行完成。
- Android1.6-> Android2.3,AsyncTask执行顺序修改为并行。当task访问同一个资源时会出现并发问题。
- Android3.0后AsyncTask修改为顺序执行,新添加了一个函数executeOnExecutor(Executor),如果需要并行执行,只需调用该函数,并把参数设置为并行即可。
- 创建一个单独的线程池(Executors.newCachedThreadPool())
- 或者使用executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Params…params)
- 源码分析
AsyncTask简介 • Asynctask具体用法? • Asynctask的Do in background方法是怎么通知UI线程刷新进度条的? • Asynctask的Do in background方法默认是返回 true ,表示任务完成,如果想返回具体的数据呢,怎么做。如果Activity被销毁了,还会执行到postexcutd方法吗?
Android基础——AsyncTask InternalHandler是在UI线程上创建的,它接收来自工作线程的消息 总结: 1、 AsyncTask的本质是一个静态的线程池,AsyncTask派生出的子类可以实现不同的异步任务,这些任务都是提交到静态的线程池中执行。 2、线程池中的工作线程执行doInBackground(mParams)方法执行异步任务 3、当任务状态改变之后,工作线程会向UI线程发送消息,AsyncTask内部的InternalHandler响应这些消息,并调用相关的回调函数
1. 流程原理
- AsyncTask如何实现在doInBackgroud()中执行耗时操作。
- 如何在onPostExecute,onProgress等中得到返回值。
- 需要了解的知识:
- Callable可以理解为产生结果。类似于Runnable,但Runnable不会返回结果,并且无法抛出返回结果的异常。
- FutureTask拿到异步执行任务的返回值。
1.1 new AsyncTask
mWorker = new WorkerRunnable<Params, Result>() {//实现了Callable类
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 {
//通过Handler和Message将结果发给InternalHandler处理
postResult(result);
}
return result;
}
mFuture = new FutureTask<Result>(mWorker) {//使用FutureTask运行Callable任务
@Override
protected void done() {
try {
//调用postResult发送给Handler去处理,然后通过onProgressUpdate返回给主线程
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
...
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
1.2 execute
- 使用执行器
SerialExecutor implements Executor
- 顺序 execute 执行任务runnable.run().
- 并行 executeOnExecutor通过判断最终还是执行exec.execute(mFuture);
2. 内存泄漏
- AsyncTask是Activity非静态内部类,持有Activity的引用。
- 在Activity销毁前cancel掉AsyncTask。Activity销毁再跑子线程对UI也没什么意义。
- 或者使用static + WeakReference的形式。
3. AsyncTask使用
• Asynctask的Do in background方法是怎么通知UI线程刷新进度条的?
• Asynctask的Do in background方法默认是返回 true ,表示任务完成,如果想返回具体的数据呢,怎么做。如果Activity被销毁了,还会执行到postexcutd方法吗? Android基础——AsyncTask
4. 提供的方法
- 主线程执行
onPreExecute
后台任务被执行完之前调用,onProgressUpdate
后台任务被执行完之后调用,onPostExecute
onCancelled()
- 子线程执行
doInBackground
后台线程执行,可以调用publishProgress
二 HandlerThread
- HandlerThread用来代替Thread。自己内部带有Looper线程,可以异步处理耗时任务。
- HandlerThread启动后,通过getLooper取出Looper(主线程),Looper对象初始化在子线程run中处理。getLooper()方法中的 wait()与run方法中的notifyAll()共同协作,实现了两个线程之间的同步。
- 实现子线程与UI线程通信,可以两个子线程之间通信
- 在使用时需要手动回收
- 使用
HandlerThread audioThread = new HandlerThread("audio_thread");
Handler audioHandler;
//启动线程
audioThread.start();
//通过fetchHandler发送的消息,会被audioThread线程创建的轮询器拉取到
audioHandler = new Handler(fetchThread.getLooper()){
@Override
public void handleMessage(Message msg) {
SystemClock.sleep(1000);
runOnUiThread(new Runnable() {
@Override
public void run() {
tv.setText("audio run");
}
});
//循环执行
audioHandler.sendEmptyMessage(1);
}
};
三 IntentService
- Service + HandlerThread + Intent
- 处理耗时任务,减轻主线程的压力
- 封装了HandlerThread的实现过程
- 启动IntentService类型的Service后,系统通过ServiceHandler将携带的Intent消息放入由HandlerThread线程生成的Looper的消息队列中,Looper依次处理队列中的消息并通过dispatchMessage将消息交给ServiceHandler的Handler来具体执行(其实就是Handler的用法,和我们在Activity中创建Handler并在handleMessage中更新ui的用法一样,只不过这里的handleMessage是在HandlerThread这样的后台线程而不是ui线程中执行的)
- 调用子类的onHandleIntent方法(用来执行费时操作),结束后关闭Service 总之,这种机制通常用于希望按顺序执行(串行)而非并发(并行)执行的费时操作, 其中每个任务执行完毕的时间是未知的的应用场景。如果希望在任务结束后通知前台可以通过sendBroadCast的方式发送广播。