多线程相关
- 【java】Handler+Looper+Message+MessageQueue 消息处理系统
- 【android】HandlerThread+Looper
【java】Handler+Looper+Message+MessageQueue 消息处理系统
- Handler为什么可以处理UI
- 各职责
- Handler、MessageQueue、Looper之间关系,以及是如何协作的
- Demo例子
- 4种方式实现其它线程访问UI线程
- 小结
1.Handler为什么可以处理UI
handler能够处理UI,因为handler在创建的时候会绑定在创建的线程上,如果handler实在在UI线程上创建的,那么他就可以操作UI。
2.各职责
- Message:消息。包括了消息ID、消息处理对象、处理的数据。由MessageQueue统一列队,最终由Handler进行处理
- Handler:处理者。负责Message的发送以及接受处理,使用Handler时,需要实现HandleMessage(Message msg)方法来对Message消息进行处理,比如更新UI
- MessageQueue:消息队列。用来存放Handler发送过来的消息,按照FIFO(先进先出)规则执行。但是,存放的Message并非实际意思的保存,而是将Message以链表的方式串联起来,等待Looper抽取
- Looper:消息泵。不断从MessageQueue抽取Message执行。因此,一个Looper需要一个MessgaeQueue
3.关系
- Handler,Looper和MessageQueue就是简单的三角关系。
- Handler与它们的关系,只是简单的聚集关系,即Handler里会引用当前线程里的特定Looper和MessageQueue。
- 多个Handler都可以共享同一Looper和MessageQueue。但是,这些Handler也就运行在同一个线程里。
下面展Handler、MessageQueue、Looper之间是如何协作的:
4.Demo例子(a.主线程发送消息到子线程。b.子线程发送消息到主线程)
- a.主线程发送消息到子线程
- b.子线程发送消息到主线程
(a)主线程发送消息到子线程例子:
public class MainActivity extends AppCompatActivity {
TextView tv;
private Handler handler;
private int i = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
new LooperThread().start();
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
i += 1;
//注意这个handler在New LooperThread().start()时候初始化了;
Message message = handler.obtainMessage(1, 1, 1, "主线程发送的消息" + i);
handler.sendMessage(message);
}
});
}
class LooperThread extends Thread {
@Override
public void run() {
super.run();
// 将当前线程初始化为Looper线程
Looper.prepare();
// 其他处理,如实例化handler
/**
* 注意了:
* ---这里的handler是定义在主线程中的
*Looper.myLooper()获得的就是该线程的Looper对象了
*/
handler = new ThreadHandlers(Looper.myLooper());
// 开始循环处理消息队列
Looper.loop();
}
class ThreadHandlers extends Handler {
public ThreadHandlers(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//这里对该线程中的MessageQueue中的Message进行处理
handler = new Handler(Looper.myLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.e("aaaaa", "子线程收到" + msg.obj);
}
};
}
}
}
}
多次点击结果为:
E/aaaaa: 子线程收到主线程发送的消息1
E/aaaaa: 子线程收到主线程发送的消息2
E/aaaaa: 子线程收到主线程发送的消息3
E/aaaaa: 子线程收到主线程发送的消息4
E/aaaaa: 子线程收到主线程发送的消息5
E/aaaaa: 子线程收到主线程发送的消息6
E/aaaaa: 子线程收到主线程发送的消息7
(b)子线程发送消息到主线程
public class MainActivity extends AppCompatActivity {
TextView tv;
private Handler handler;
private int i = 0;//记数,记录点击的次数
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new LooperThread(i++).start();
}
});
}
class LooperThread extends Thread {
int i = 0;
public LooperThread(int i) {
this.i = i;
}
@Override
public void run() {
super.run();
//主线程的Looper对象
Looper looper = Looper.getMainLooper();
//使用主线程的Looper对象来创建Handler,因此这个Handler发送的Message会传递给主线程的MessageQueue
handler = new UIHandlers(looper);
Message message = handler.obtainMessage(1, 1, 1, "子线程发送消息" + i);
handler.sendMessage(message);
}
}
class UIHandlers extends Handler {
public UIHandlers(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//更新UI
tv.setText(msg.obj + "");
Log.e("aaa", msg.obj + "");
}
}
}
多次点击结果为:
06-03 00:24:38.983 15698-15698/com.example.administrator.demo E/aaa: 子线程发送消息0
06-03 00:24:40.023 15698-15698/com.example.administrator.demo E/aaa: 子线程发送消息1
06-03 00:24:40.523 15698-15698/com.example.administrator.demo E/aaa: 子线程发送消息2
06-03 00:24:40.753 15698-15698/com.example.administrator.demo E/aaa: 子线程发送消息3
06-03 00:24:40.953 15698-15698/com.example.administrator.demo E/aaa: 子线程发送消息4
06-03 00:24:41.163 15698-15698/com.example.administrator.demo E/aaa: 子线程发送消息5
5.6种方式实现其他线程访问UI线程
- Handler与Message机制:通过显示的抛出、捕获消息与UI进行交互
- Activity.runOnUiThread(Runnable):如果当前线程为ui线程,则立即执行;否则,将参数中的线程操作放入到ui线程的事件队列中,等待执行。
- View.post(Runnable):在线程里面发送消息。然后在handler的dispatchMessage()方法里面进行处理
- View.postDelayed(Runnable,long):跟上面一样,只是多了个带有延迟的
- 使用AsyncTask直接更新UI
- 2~6条其实底层实现都是Handler的通信机制(注意:为什么handelr在子线程创建不调用Looper.prepare()不行),详细介绍可以参考郭神的博文:http://blog.csdn.net/guolin_blog/article/details/9991569
6.小结
- Handler的处理过程,运行在创建的Handler的线程里
- 一个Looper对应一个MessageQueue
- 一个线程对应一个Looper
- 一个Looper可以对应多个Handler
- 不确定当前线程时,更新UI尽量调用post方法
【android】HandlerThread+Looper
- 使用步骤
- HandlerThread优势
- 测试Demo
1.使用步骤
//1.创建一个HandlerThread,即创建了一个包含Looper的线程。
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
//2.获取HandlerThread的Looper
Looper looper = handlerThread.getLooper();
//3.创建Handler,通过Looper初始化
Handler handler = new Handler(looper);
//注意:
//a.通过以上三步我们就成功创建HandlerThread。通过handler发送消息,就会在子线程中执行。
//b.如果想让HandlerThread退出,则需要调用handlerThread.quit();。
2.HandlerThread的优势
Android使用Looper机制才能接收消息和处理计划任务,上面的代码编写起来实在是麻烦,所以Android提供了一个线程类HanderThread类,HanderThread类继承了Thread类,它封装了Looper对象,使我们不用关心Looper的开启和释放的细节问题。HandlerThread对象中可以通过getLooper方法获取一个Looper对象引用。
3.测试Demo
public class MainActivity extends AppCompatActivity {
TextView tv;
private Handler handler;
private boolean isRunning;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// handler.postDelayed(runnable, 1000);
Message message = handler.obtainMessage(1, 1, 1, "发送消息");
handler.sendMessage(message);
}
});
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
Looper looper = handlerThread.getLooper();
handler = new UIHandlers(looper);
}
class UIHandlers extends Handler {
public UIHandlers(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//子线程
Log.e("aaa", msg.obj + "");
}
}
// private Runnable runnable = new Runnable() {
// @Override
// public void run() {
// Log.e("aaa", "HandlerThread.");
// try {
// Thread.sleep(200);
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
// };
@Override
protected void onResume() {
super.onResume();
isRunning = true;
}
@Override
protected void onStop() {
super.onStop();
isRunning = false;
}
@Override
protected void onDestroy() {
super.onDestroy();
isRunning = false;
// handler.removeCallbacks(runnable);
}
}
//多次点击执行结果为:
06-03 00:54:28.693 18284-18346/com.example.administrator.demo E/aaa: 发送消息
06-03 00:54:29.503 18284-18346/com.example.administrator.demo E/aaa: 发送消息
06-03 00:54:30.073 18284-18346/com.example.administrator.demo E/aaa: 发送消息
06-03 00:54:31.143 18284-18346/com.example.administrator.demo E/aaa: 发送消息