学习视频(推荐慕课网视频):https://www.imooc.com/video/5519
1、是什么
是android提供的用来更新UI的一套机制,也是一套消息处理的机制
2、怎么用
a、通过sendMessage()方法(其内部调用sendMessageDelayed)
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView textView;
//1、创建Handler
private Handler handler ;
@SuppressLint("HandlerLeak")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.text);
findViewById(R.id.button).setOnClickListener(this);
//2、实现handlerMessage()方法
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
textView.setText(msg.obj.toString());
}
};
}
@Override
public void onClick(View v) {
new Thread(){
@Override
public void run() {
//3、创建一个Message,通过new或者使用Message.Obtain()方法
Person person = new Person("张三",44);
Message message = new Message();
message.obj = person;
//4、调用sendMessage方法发送消息
handler.sendMessage(message);
}
}.start();
}
}
b、通过post()方法(其内部也是调用sendMessageDelayed)
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView textView;
//1、创建Handler
private Handler handler = new Handler();
@SuppressLint("HandlerLeak")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.text);
findViewById(R.id.button).setOnClickListener(this);
}
@Override
public void onClick(View v) {
new Thread(){
@Override
public void run() {
//调用post方法
handler.post(new Runnable() {
@Override
public void run() {
textView.setText("update Thread");
}
});
}
}.start();
}
}
3、原理
Message:消息,可通过new Message()或者Message.obtain获得(推荐使用Message.obtain()来获取Message实例,因为在Message类里面定义了一个消息池,当消息池里存在未使用的消息时,便返回,如果没有未使用的消息,则通过new的方式创建返回,所以使用Message.obtain()的方式来获取实例可以大大减少当有大量Message对象而产生的垃圾回收问题。)
MessageQueue:消息队列(这里有必要提一下MessageQueue的数据结构,是一个单向链表,Message对象有个next字段保存列表中的下一个,MessageQueue中的mMessages保存链表的第一个元素。)
Looper:每一个线程只有一个Looper,每个线程在初始化Looper之后,然后Looper会维护好该线程的消息队列,用来存放Handler发送的Message,并处理消息队列出队的Message。
不管post还是sendMessage方法,最后的本质都是一样的,因此以sendMessage为例介绍整个流程:子线程调用sendMessage方法,经过内部一系列函数调用,将Message对象添加到Looper创建的MessageQueue队列中,同时给Message指定了target对象(Handler),此时,Looper.loop()方法从Looper的成员变量MessageQueue队列中调用Message的target对象的dispatchMessage方法(也就是msg.target.dispatchMessage方法)取出Message,然后在dispatchMessage方法中调用Message的target对象的handleMessage()方法(也就是msg.target.handleMessag)
源码:
Handler、Looper、MessageQueue如何关联:
Handler.Handler():通过Looper.myLooper()获得Looper
Looper.myLooper():通过sThreadLocal.get()获得Looper的,(关于ThreadLocal:不同的线程访问同一个ThreadLocal,不管是get方法还是set方法对其所做的操作,仅限于各自线程内部。这就是为什么用ThreadLocal来保存Looper,因为这样才能使每一个线程有单独唯一的Looper。)
Looper.perpare():通过new Looper创建Looper,并通过sThreadLocal.set方法保存Looper
4、Handler引起的内存泄漏
原因:handler非静态内部类持有外部类的匿名引用,导致外部类无法被回收
解决办法:handler内部持有外部Activity的弱引用,并把handler改为静态内部类,然后在onDestroy方法中调用handler的removeCallBack()方法