前言
主线程可以向子线程发送消息吗?如果可以怎样实现?
子线程可以向子线程发送消息吗?
面试时被面试官问过两次这样的问题都没有回答上来,所以今天查阅了一些资料来补充一下这里的知识。
子线程向主线程发送消息
由于android不允许在主线程做耗时的操作,子线程又不能更新UI,所以我们工作中大多用的都是在子线程中请求处理数据,然后将数据发送到主线程,来更新UI,所以我们经常用到的都是子线程向主线程发送消息,大家都不陌生就不多说了。
主线程向子线程发送消息
我们首先要确定一个事情:哪个线程要处理消息,Handler就必须绑定到哪个线程
其实简单的逻辑就是创建一个Handler,然后在一个线程中发送消息,另一个线程中处理消息。Handler将消息发送到消息队列MessageQueue中,消息队列是由Looper来负责管理的,所以我们首先要得到一个Looper。但是有的同学就有疑问了,为啥我们平时写代码时没有管什么looper啊,那是因为我们在主线程创建的Handler,而主线程默认帮我们完成了Looper的操作,所以如果我们从主线程向子线程发送消息,Handler是子线程的的,我们必须在子线程中自己完成Looper的操作。
我们再来具体的说下这个Looper是什么。
它就像一个消息队列(MessageQueue)的管家(Looper),一个消息队列只有一个管家,并且管理者整个消息队列,而一个消息队列内可以容纳多个消息(Message),而工人(Handler)也可以有多个,管家派遣他们向消息队列中存储或取出消息后执行任务;
所以它们的个数如下:
管家(Looper): 1 个;
消息队列(MessageQueue):1 个;
消息(Message):可以多个;
工人(Handler):可以多个;
Looper的部分源码:
//ThreadLocal可以理解为一个存储Looper的列表;
ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//Looper的构造器
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
1.Looper.prepare()完成了如下操作:
sThreadLocal.set(new Looper(quitAllowed));
2.Looper.loop()完成了如下操作:
Looper me = sThreadLocal.get();
MessageQueue queue = me.mQueue;
……
//不断循环分发消息
for (;;) {
Message msg = queue.next();
……
msg.target.dispatchMessage(msg);
//dispatchMessage(msg)方法执行如下内容:
handler.handleMessage(msg);//handler执行handleMessage(msg)中的代码;
……
};
简单实例
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final MyThread thread = new MyThread();
thread.start();
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Message message = Message.obtain();
message.what = 2;
thread.handler.sendMessage(message);
}
});
}
class MyThread extends Thread{
private Handler handler;
@Override
public void run() {
super.run();
Looper.prepare();
handler = new Handler(){ //handler必须在在线程的run方法中创建
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Toast.makeText(MainActivity.this,"MyThread handler 收到消息 :"+msg.what,Toast.LENGTH_LONG).show();
}
};
Looper.loop();
}
}
}
Looper.prepare() 和Looper.loop() 就是所说的我们要在子线程中要自己完成的Looper操作。
子线程向子线程发送消息
class MyThread extends Thread{
public Handler handler;
@Override
public void run() {
super.run();
Looper.prepare();
handler = new Handler(){ //handler必须在在线程的run方法中创建
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Toast.makeText(MainActivity.this,"MyThread handler 收到消息 :"+msg.what,Toast.LENGTH_LONG).show();
}
};
Looper.loop();
}
}
其实只要我们知道了上面的和代码,建立一个线程类,先获取Looper对象,然后在run方法中绑定一个Handler,然后启动消息循环,我们就可以在任何时间地点通过创建线程类对象,从而获取他的handler成员变量来发送消息。所以子线程也可以向子线程发送消息。
public class MainActivity extends AppCompatActivity {
YourThread yourThread;
MyThread myThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
yourThread = new YourThread();
yourThread.start();
}
});
myThread = new MyThread();
myThread.start();
}
class MyThread extends Thread{
private Handler handler;
@Override
public void run() {
super.run();
Looper.prepare();
handler = new Handler(){ //handler必须在在线程的run方法中创建
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Toast.makeText(MainActivity.this,"MyThread handler 收到消息 :"+msg.what,Toast.LENGTH_LONG).show();
}
};
Looper.loop();
}
}
class YourThread extends Thread{
@Override
public void run() {
super.run();
Message message = Message.obtain();
message.what = 3;
myThread.handler.sendMessage(message);
}
}
}
网友评论