一、概述
Handler是一套消息传递机制,通常的作用是在多线程的应用场景中。Handler机制涉及的主要组件包括Handler、Looper、Message和MessageQueue。
以下是这些组件的详细介绍:
- Handler。消息处理者,负责发送和处理消息。
- Message。消息的主体,包含消息的具体内容和类型。
- MessageQueue。消息队列,用于存储和顺序分发消息。
- Looper。消息循环器,负责从MessageQueue中取出消息并分发给Handler处理。
每个Handler对象都绑定到一个线程的Looper,这意味着它只能处理由该线程创建的消息。这种机制允许主线程(UI线程)以外的线程执行耗时操作,同时确保这些操作的结果能够安全地更新到UI上。例如,当一个线程进行网络请求或文件处理时,它可以在子线程中发送消息到Handler,然后由Handler将这些消息放入MessageQueue中,主线程(UI线程)的Looper会从MessageQueue中取出这些消息,并分发给相应的Handler对象进行处理,从而实现UI更新。
二、Handler对象创建问题
在子线程中创建Handle对象需要调用Looper.prepare()方法后,才能够创建Handler。在主线程中会自动地调用Looper.prepare()方法。
public class MainActivity extends AppCompatActivity {
private Handler handler1;
private Handler handler2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler1 = new Handler();//主线程创建Handle
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();//子线程中创建Handle需要先调用此方法
handler2 = new Handler();
}
}).start();
}
}
三、使用方法
方式一:使用Handler.sendMessage()
在该使用方式中,因创建Handler的方式不同,又可分两种:创建Handler子类、使用匿名Handler内部类,但本质都是相同的,都是继承Handler类创建子类。
1、创建Handler子类
public class MainActivity extends AppCompatActivity {
TextView mTxtShowTest;
Button mBtn1, mBtn2, mBtn3;
// 2、在主线程中创建自定义Handler(mHandler)的实例
private mHandler mhandler = new mHandler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTxtShowTest = (TextView) findViewById(R.id.mTxtShowTest);
mBtn1 = (Button) findViewById(R.id.mBtn1);
mBtn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
// 3、创建所需消息对象
Message msg = Message.obtain();
msg.what = 1;
//4、发送消息
mhandler.sendMessage(msg);
}
// 5、开启线程
}).start();
}
});
}
//1、自定义Handler子类,继承Handler,重写handleMessage()方法
class mHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//执行的UI操作
mTxtShowTest.setText("新建Handler子类方法");
}
}
}
2、使用匿名Handler子类
public class MainActivity extends AppCompatActivity {
TextView mTxtShowTest;
Button mBtn1, mBtn2, mBtn3;
//1、在主线程中通过匿名内部类创建Handler类对象
private Handler mhandler2 = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//执行的UI操作
mTxtShowTest.setText("匿名内部类方法");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTxtShowTest = (TextView) findViewById(R.id.mTxtShowTest);
mBtn2 = (Button) findViewById(R.id.mBtn2);
mBtn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
// 2、创建所需消息对象
Message msg = Message.obtain();
msg.what = 1;
//3、发送消息
mhandler2.sendMessage(msg);
}
//4、开启线程
}).start();
}
});
}
}
方式二、使用Handler.post()方法
public class MainActivity extends AppCompatActivity {
TextView mTxtShowTest;
Button mBtn1, mBtn2, mBtn3;
//1、在主线程中创建Handler的实例
private Handler mhandlerPost = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTxtShowTest = (TextView) findViewById(R.id.mTxtShowTest);
mBtn3 = (Button) findViewById(R.id.mBtn3);
mBtn3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
//2、在子线程中使用Handler.post()
mhandlerPost.post(new Runnable() {
@Override
public void run() {
//执行的UI操作
mTxtShowTest.setText("post方法");
}
});
}
//4、开启线程
}).start();
}
});
}
}
四、Handler内存泄漏
在Java中,非静态内部类会持有一个外部类的隐式引用,可能会造成外部类无法被GC;
比如这里的Handler,就是非静态内部类,它会持有Activity的引用从而导致Activity无法正常释放。
而单单使用静态内部类,Handler就不能调用Activity里的非静态方法了,所以加上「弱引用」持有外部Activity。
private static class MyHandler extends Handler {
//创建一个弱引用持有外部类的对象
private final WeakReference<MainActivity> content;
private MyHandler(MainActivity content) {
this.content = new WeakReference<MainActivity>(content);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
MainActivity activity= content.get();
if (activity != null) {
switch (msg.what) {
case 0: {
activity.notifyUI();
}
}
}
}
}
转换成Kotlin:(Tips:Kotlin 中的内部类,默认是静态内部类,使用inner修饰才为非静态~)
private class MyHandler(content: MainActivity) : Handler() {
//创建一个弱引用持有外部类的对象
private val content: WeakReference<MainActivity> = WeakReference(content)
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
val activity = content.get()
if (activity != null) {
when (msg.what) {
0 -> {
activity.notifyUI()
}
}
}
}
}
网友评论