前言
- 我们都知道Android的UI线程是不安全,在子线程中更新UI会造成程序崩溃,但是我们有时候确实需要在子线程中进行耗时操作,然后再依据结果更新UI
在学习具体的方法前我们首先看一下Android的异步消息处理机制示意图
我们再来把异步消息处理的整个流程梳理一下:
- 首先需要在主线程当中创建一个Handler对象,并重写handleMessage()方法。
- 然后当子线程中需要进行UI操作时,就创建一个Message对象,并通过Handler将这条消息发送出去。
- 之后这条消息会被添加到MessageQueue的队列中等待被处理
- 而Looper则会一直尝试从MessageQueue中取出待处理消息,最后分发回Handler的handlerMessage()方法中。
方法总结
1.使用Handler
在主线程中创建Handler:
public android.os.Handler handler=new android.os.Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case UPDATE_TEXT:
textView.setText(msg.obj.toString());
break;
default:
break;
}
}
};
在子线程中调用sendMessage方法更新UI
注意:这里的sendHttpRequest是OkHttp提供的回调接口,是在子线程中运行的
HttpUtil.sendHttpRequest(address,new okhttp3.Callback(){
@Override
public void onResponse(Call call, Response response) throws IOException {
String responseData = response.body().string();
Message message = new Message();
message.what=UPDATE_TEXT;
message.obj=responseData;
handler.sendMessage(message);
}
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
});
2.使用runInUiThread()方法
这表面看起来是一个很简单的方法,但其实它就是一个异步消息处理机制的接口封装,背后的实现原理其实和上图的描述是一样的。
private void showResponse(final String response){ runOnUiThread(new Runnable() { @Override public void run() { textView.setText(response); } }); }
3.使用AsyncTask
这种方法看起来需要编写更多的代码,但是实际上在语义方面会更加清晰
@Override protected void onPreExecute() { //这个方法会在后台任务开始执行之前调用,用于进行一个界面上的初始化操作 super.onPreExecute(); } @Override protected Object doInBackground(Object[] params) { //这个方法中的所有代码都会在子线程中运行,我们应该在这里去处理所有的耗时任务。 //任务一旦完成就可以通过return语句来将任务的执行结果返回。 //注意:在这个方法中是不可以进行UI操作的。 return null; } @Override protected void onProgressUpdate(Object[] values) { //当调用publishProgress()方法传入当前的下载进度时。 //onProgressUpdate()方法就会很快被调用,在这里就可以就行UI操作了 super.onProgressUpdate(values); } @Override protected void onPostExecute(Object o) { //当doInBackground()方法返回时,onPostExecute()方法就会很快的被调用 //执行一些任务的收尾工作 super.onPostExecute(o); }
后记
- 查资料时发现还有view.post方法,但是在这次实验中并没有用到,以后再接着补充
- 这几篇文章是我学习的时候看过的,上述这篇文章也是对这几篇文章的总结加上自己的一点小感悟写出来的。
- 同时这几篇文章中还有涉及到内部源码分析的,目前自己写的只是将如何用写出来而已。有时间的时候再深入学习更新记录
- 知识梳理:Android子线程中更新UI的3种方法
- Android异步消息处理机制完全解析,带你从源码的角度彻底理解
- 浅谈Android消息异步处理机制