AsyncTask
AsyncTask主要用来更新UI线程,比较耗时的操作可以在AsyncTask中使用。
AsyncTask是个抽象类,使用时需要继承这个类,然后调用execute()方法。注意继承时需要设定三个泛型Params,Progress和Result的类型,如AsyncTask<Void,Inetger,Void>:
Params是指调用execute()方法时传入的参数类型和doInBackgound()的参数类型
Progress是指更新进度时传递的参数类型,即publishProgress()和onProgressUpdate()的参数类型
Result是指doInBackground()的返回值类型
上面的说明涉及到几个方法:
doInBackgound() 这个方法是继承AsyncTask必须要实现的,运行于后台,耗时的操作可以在这里做
publishProgress() 更新进度,给onProgressUpdate()传递进度参数
onProgressUpdate() 在publishProgress()调用完被调用,更新进度
使用AsyncTask的注意事项
① 必须在UI线程中创建AsyncTask的实例.
② 只能在UI线程中调用AsyncTask的execute方法.
③ AsyncTask被重写的四个方法是系统自动调用的,不应手动调用.
④ 每个AsyncTask只能被执行(execute方法)一次,多次执行将会引发异常.
⑤ AsyncTask的四个方法,只有doInBackground方法是运行在其他线程中,其他三个方法都运行在UI线程中,也就说其他三个方法都可以进行UI的更新操作.
HandlerThread:
常规使用步骤
1.创建实例对象
2.启动HandlerThread线程
3.构建循环消息处理机制
4.构建异步handler
HandlerThread使用示例
public class MainActivity extends AppCompatActivity {
private HandlerThread myHandlerThread;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建一个线程,线程名字:handler-thread
myHandlerThread = new HandlerThread("handler-thread");
myHandlerThread.start();
//在这个线程中创建一个handler对象
handler = new Handler(myHandlerThread.getLooper()){
@Override
public void handleMessage(Message msg) {
//这个方法是运行在 handler-thread 线程中的 ,可以执行耗时操作
Log.d( "handler " , "消息: " + msg.what + " 线程: " + Thread.currentThread().getName() ) ;
}
};
//在主线程给handler发消息
handler.sendEmptyMessage(1);
new Thread(new Runnable() {
@Override
public void run() {
//在子线程给handler发消息
handler.sendEmptyMessage(2);
}
}).start();
}
@Override
protected void onDestroy() {
super.onDestroy();
myHandlerThread.quit();
}
}
HandlerThread的特点
1.HandlerThread本质上是一个线程类,它继承了Thread;
2.HandlerThread有自己的内部Looper对象,可以进行looper循环;
3.通过获取HandlerThread的looper对象传递给Handler对象,可以在handleMessage方法中执行异步任务。
4.创建HandlerThread后必须先调用HandlerThread.start()方法,Thread会先调用run方法,创建Looper对象。
Android消息循环机制总结
程序启动的时候,主线程会创建一个Looper对象。Looper对象内部维护一个MessageQueue,然后调用loop()方法循环去读取消息。
初始化Handler的时候,在Handler的构造函数内部,会获取当前线程的Looper对象,进而获取MessageQueue对象。由此可见,想要操作UI的Handler必须在主线程中创建。否则会提示你:【”Can’t create handler inside thread that has not called Looper.prepare()”】
调用Handler的先关方法时,会获取Message对象,将消息对象的target指向当前handler对象,然后放到消息队列中。
loop()工作中,会从消息队列中获取一个个的消息,调用handle的dispatchMessage(msg)分发处理。
Message内部维护一个消息池,用来回收缓存message对象。
Looper相当于一个发动机,MessageQueue相当于流水线,Message相当于一个个的物品,而Handler就相当于工人。