文章目录
概念介绍
【消息机制中的角色】
Message:消息的载体,用于封装消息的相关数据
Handler:消息的发送者与处理者,用于发送消息,并处理消息
MessageQueue:(在编程时不会使用到)消息队列,若干个消息的容器
Looper:轮询者,从消息队列中获取数据,并交给运行在主线程的 Handler 进行处理
xml
xml中增加一个按钮来发送消息
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/btn_send_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发出消息" />
</LinearLayout>
MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btnSendMsg;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnSendMsg = findViewById(R.id.btn_send_msg);
btnSendMsg.setOnClickListener(this);
handler = new Handler(new InnerHandlerCallback());
}
@Override
public void onClick(View view) {
//发出消息
Message msg = Message.obtain(handler);
msg.sendToTarget();
Log.d("Handler", "[Thread ID:]" + Thread.currentThread().getId() + " MainActivity onclick()->send message");
}
private class InnerHandlerCallback implements Handler.Callback {
@Override
public boolean handleMessage(Message message) {
Log.d("Handler", "[Thread ID:]" + Thread.currentThread().getId() + " InnerHandlerCallback handleMessage()->handle message");
return false;
}
}
}
运行程序,查看日志,从日志可以看出 Handler 是运行在主线程的
现在修改 onClick 中代码,把发送消息放在子线程中
@Override
public void onClick(View view) {
new Thread() {
@Override
public void run() {
//发出消息
Message msg = Message.obtain(handler);
msg.sendToTarget();
Log.d("Handler", "[Thread ID:]" + Thread.currentThread().getId() + " MainActivity onclick()->send message");
}
}.start();
}
运行程序,查看日志,可以看到发消息在子线程,处理消息还是在主线程
如果把创建 Handler 也放在子线程中
@Override
protected void onCreate(Bundle savedInstanceState) {
......
new Thread() {
@Override
public void run() {
Looper.prepare();
handler = new Handler(new InnerHandlerCallback());
Log.d("Handler", "[Thread ID:]" + Thread.currentThread().getId() + " MainActivity onCreate()->sub thread->new Handler");
Looper.loop();
}
}.start();
}
运行程序,观察日志,会发现 handle message 是同一个线程:
【Handler与Looper】
Handler 运行在哪个线程(在哪个线程上处理消息),取决于创建 Handler 时,关联到哪个线程上的 Looper,如果没有显示指定 Looper,则关联到当前线程
【小结】
1、在主线程创建的 Handler 对象,是运行在主线程的,所以可以直接更新 UI
2、在子线程中创建 Handler 之前,必须调用 Looper.prepare()
以初始化运行在子线程中的 Looper
3、在子线程中的 Looper 必须显式的调用 Looper.loop()
方法,才会开始轮询消息队列
4、在主线程中,默认就已经存在处于轮循工作状态的 Looper,而子线程中没有
5、如果没有可用的 Looper,则无法创建 Handler
6、创建 Handler 时,会默认关联当前线程上的 Looper
MessageQueue 是消息队列的意思,它主要用于存放所有通过 Handler 发送的消息。 这部分消息会一直存在于消息队列中,等待被处理。每个线程中只会有一个 MessageQueue 对象
Looper 是每个线程中的 MessageQueue 的管家,调用 Looper 的 loop()
方法后,就会进入到一个无限循环当中,然后每当发现 MessageQueue 中存在一条消息,就会将它取出,并传递到 Handler 的 handleMessage()
方法中。每个线程中也只会有一个 Looper 对象