Android多线程编程
Android中对于耗时任务不应该在主(UI)线程中执行,一般需要新建子线程来执行这些耗时任务。
Android多线程编程不比Java特殊,基本用法是一样的,都是使用相同的语法。Android中定义一个线程可以使类继承致Thread或者时实现Runnable接口,然后重写run方法。
下面是一个例子:
class MyThread extends Thread{
@Overwrite
public void run(){
//耗时任务
}
}
使用:new MyThread().start();
实现Runnable接口
class MyThread implements Runnable{
@Overwrite
public void run(){
//耗时任务
}
}
使用:new Thread(new MyThread()).start();
如果不想实现Runnable接口也可以:
new Thread(new Runnable(){
@Overwrite
public void run(){
//耗时任务
}
}).start();
Android的UI是线程不安全的,也就是说想要更新程序中的UI只能在UI线程,否则会出现异常。为什么限制只能在主线程中更改UI呢?原因是如果不限制的话,可能出现在两个或者两个以上的线程在同一时间操作某个UI控件,这个的话就会发生冲突。
有时需要在子线程执行耗时任务,当执行完任务之后拿到结果需要去更新UI时,这个时候不能直接在子线程中更新UI。Android提供了一套异步消息机制,完美解决了子线程中更新UI操作的问题。
异步消息处理机制
Android中的异步消息处理机制主要由4个部分组成:Message、Handler、MessageQueue、和Looper。
1、Message
Message是线程之间传递的消息,它内部可以携带少量的信息,用于在不同的线程之间交换数据。
2、Handler
Handler是处理者的意思,它主要用于发送和处理消息。发送消息一般是使用Handler的sendMessage方法,消息经过一系列的辗转之后,会回到Handler的handMessage方法中。
3、MessageQueue
MessageQueue是消息队列的意思,它用于存放所有通过Handler发送的消息。Handler发送出来的消息会存放在MessageQueue中等待处理。每个线程只会有一个MessageQueue对象。
4、Looper
Looper是每个线程中MessageQueue的管家,调用Looper中的loop()方法后,就会进入到一个无限循环中,它会一直循环检查MessageQueue中是否还有消息,如果有,就将它取出来,送到Handler的handMessage方法中。每个线程也只有一个Looper对象。
异步消息处理机制中消息的传递流程是:首先在主线程中创建一个Handler对象,然后重写这个Handler对象的handMessage()方法。当子线程中需要更新UI时,就创建一个Message对象,将需要传递的数据信息保存在这个Message对象中,然后调用Handler对象的sendMessage()方法将这个Message对象添加到MessageQueue中,然后Looper在不断循环中就会发现这个消息,接着它就会把这个消息取出来处理,最后分发给Handler对象的handMessage()方法。这样就将消息从子线程转到了主线程。
这里需要注意一下,MessageQueue对象和Looper对象在每个线程中都只有一个,而主线程中的这两个对象时系统自动帮我们创建了的。我们无需自己创建。
runOnUiThread()方法实现的原来也是使用上述的异步消息机制。
既然这里说线程都可以有MessageQueue对象和Looper对象。那么考虑一个问题,是不是也可以在主线程中发送一个消息给子线程,然后子线程来处理呢?
答案是可以的,下面是一个示例
public class MainActivity
extends AppCompatActivity {
private static final String TAG = "MainActivity";
private Handler
myHandler
;
@Override
protected void
onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
;
setContentView(R.layout.
activity_main)
;
Button sendMessageBtn = (Button) findViewById(R.id.
btn_send_message)
;
sendMessageBtn.setOnClickListener(
new View.OnClickListener() {
@Override
public void
onClick(View view) {
Message message =
new Message()
;
message.
what =
12
;
myHandler.sendMessage(message)
;
}
})
;
childThread()
;
}
private void
childThread(){
new Thread(
new Runnable() {
@Override
public void
run() {
// 准备一个 Looper,Looper 创建时对应的 MessageQueue 也会被创建
Looper.
prepare()
;
myHandler =
new Handler(){
@Override
public void
handleMessage(Message msg) {
if (msg.
what==
12){
Log.
d(
TAG
,
"1351545454")
;
}
}
}
;
// Looper 开始不断的从 MessageQueue 取出消息并再次交给 Handler 执行
// 此时 Lopper 进入到一个无限循环中,后面的代码都不会被执行
Looper.
loop()
;
}
}).start()
;
}
}