一.面试提问
1.Handler是什么?
是Android提供的更新UI的一套机制,也叫做消息处理机制。我们可以通过它实现跨线程的发送消息和处理消息。
2.Handler的作用是什么?
实现跨线程的消息处理,主要用于主线程更新UI操作等。
二.Handler的基本使用
1.利用sendMessage()方法发送消息:
(1)发送消息的种类:
handler.sendEmptyMessage();//发送空消息
handler.sendMessage(message);//发送携带数据的消息
handler.sendMessageDelayed(message,1000);//延迟1000ms后发送携带数据的消息
(2)具体使用:
public class MainActivity extends AppCompatActivity {
private Handler mHandler;
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = findViewById(R.id.textview);
createHandler();
childThreadSend();
}
//创建主线程的handler
private void createHandler() {
mHandler = new Handler() {
//主线程处理消息
@Override
public void handleMessage(Message msg) {
//下面是具体的消息处理
String obj = (String) msg.obj;
mTextView.setText(obj);
}
};
}
private void childThreadSend() {
//开启子线程
new Thread(new Runnable() {
@Override
public void run() {
//子线程发送消息
Message message = new Message();
message.obj = "message";
mHandler.sendMessage(message);
}
}).start();
}
}
2.利用post()方法发送消息:
public class MainActivity extends AppCompatActivity {
private Handler mHandler;
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = findViewById(R.id.textview);
createHandler();
childThreadSend();
}
//创建主线程的handler
private void createHandler() {
mHandler = new Handler();
}
private void childThreadSend() {
//开启子线程
new Thread(new Runnable() {
@Override
public void run() {
//子线程发送消息
mHandler.post(new Runnable() {
//主线程处理消息
@Override
public void run() {
mTextView.setText("message");
}
});
}
}).start();
}
}
3.利用postDelayed()方法发送消息:
用处:需要定时的完成一些事情(比如定时更换TextView的文字)时,就可以利用它延迟执行的这一特点来实现。
4.向子线程发送消息
上述例子都是向主线程发送消息(包含子线程向主线程发送消息、主线程向主线程发送消息),现在介绍一下怎么向子线程发送消息:
(1)具体例子
public class MainActivity extends AppCompatActivity {
private Handler mHandler;
private TextView mTextView;
private int FLAG = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = findViewById(R.id.textview);
createHandler();
childThreadSend();
}
//接收消息的子线程相关配置
private void createHandler() {
//创建一个接收消息的子线程
MyThread myThread = new MyThread();
//开启线程
myThread.start();
//系统闹钟延时100ms,防止myLooper空指针
SystemClock.sleep(100);
//创建一个具有接收消息的子线程Looper的Handler对象
mHandler = new Handler(myThread.myLooper) {
@Override
public void handleMessage(Message msg) {
//下面是具体的消息处理
if (msg.what == FLAG) {
/**
* 子线程处理消息
*/
String obj = (String) msg.obj;
//注意更新UI一定是在主线程中进行的,这里需要切换线程
runOnUiThread(new Runnable() {
@Override
public void run() {
mTextView.setText(obj);
}
});
}
}
};
}
private void childThreadSend() {
//开启子线程
new Thread(new Runnable() {
@Override
public void run() {
//子线程发送消息
Message message = new Message();
message.obj = "message";
message.what = FLAG;
mHandler.sendMessage(message);
}
}).start();
}
//内部类:接收消息的子线程
private class MyThread extends Thread {
private Looper myLooper;
@Override
public void run() {
//准备Looper
Looper.prepare();
//创建Looper对象
myLooper = Looper.myLooper();
//开启loop
myLooper.loop();
}
}
}
(2)改进方法
注意上述代码里面系统睡眠100毫秒,其实是因为MyThread在调用start方法后,进行了创建Handler的操作,在创建Handler时需要在构造方法中传入MyThread的Looper,而只有当MyThread开启调用run()方法后才会创建出Looper,两者操作是在不同线程中,所以不能确定谁会先被执行,为了避免空指针的出现,所以进行延时。
为了进行改进,可以直接使用HandlerThread代替自定义的内部类MyThread即可,具体使用此处省略。
三.Handler深层次挖掘