Android 是不容许在子线程中进行 UI 操作的,但是有些时候我们必须在子线程里去执行一些耗时任务,然后根据执行的结果来更新相应的 UI 控件,对于这种情况,Android 提供了一套异步消息处理机制,完美解决了在子线程中进行 UI 相关操作的问题,今天我们就来一起学习一下这个 Android 系统提供的异步消息处理机制,下面是我们学习的内容大纲
一、什么是 Handler
Handler 是 Android 给我们提供的用来更新 UI 的一套机制,也是一套消息处理机制,我们可以通过它发送消息和处理消息
二、如何使用 Handler
首先我们来创建一个 HandlerTest 项目,用来演示 Handler 相关的操作
MainActivity 中的代码如下:
/**
* Handler 测试
*/
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView textView;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(this);
}
/**
* 响应点击事件
*
* @param v
*/
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
//点击按钮在子线程中更新 UI
new Thread(new Runnable() {
@Override
public void run() {
textView.setText("world");
}
}).start();
break;
}
}
}
代码非常简单,这里我们创建了一个子线程并在子线程中进行 UI 更新,发现程序 Crash 掉,报出如下错误:
这就是说着子线程中不能更新 UI 的操作,由此正是 Android 确实是不能在主线程中更新 UI 的,接下来我们来修改 MainActivity 中的代码如下:
/**
* Handler 测试
*/
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView textView;
private Button button;
private static final int UPDATE_TEXT = 1;
private Handler handler = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(this);
//在主线程中创建Handler,并从写 handleMessage 方法
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case UPDATE_TEXT :
//在这里可以进行UI操作
textView.setText("world");
break;
}
}
};
}
/**
* 响应点击事件
*
* @param v
*/
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
//点击按钮在子线程中更新 UI
new Thread(new Runnable() {
@Override
public void run() {
//创建 Message 对象
Message message = new Message();
message.what = UPDATE_TEXT;
//将 Message 对象发送出去
handler.sendMessage(message);
}
}).start();
break;
}
}
}
这里我们先是定义了一个整型常量 UPDATE_TEXT,用于表示更新 TextView 这个动作,然后新增一个 Handler 对象,并在 onCreate() 方法中把对象创建出来,并重写了父类的 handleMessage() 方法,在这里对具体的 Message 进行处理,如果发现 Message 的 what 值等于
UPDATE_TEXT,就将 TextView 的显示内容修改为 world,接下来在点击事件中,我们在子线程中并没有进行 UI 的更新,而是创建了 Message 对象,并将它的 what 字段值自定为 UPDATE_TEXT,然后调用 Handler 的sendMessage() 方法将这条 Message 发送出去,很快 Handler 就会收到这条消息,并在 handleMessage() 方法中对这条消息进行处理,需要注意的是,此时的 handleMessage() 方法就是运行在主线程当中的了,我们可以在这里进行 UI 操作
三、Handler 原理是什么
Android 中异步消息处理机制主要由 4 部分组成:Message、Handler、MessageQueue 和 Looper,接下来我们就对这 4 个部分进行简单的介绍
1. Message
Message 是在线程之间传递消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据,上面我们使用了 Message 的 what 字段,除此之外我们还可以使用 arg1 和 arg2 字段来携带一些整形数据,使用 obj 来携带一个 Object 对象
2. Handler
Handler 是消息的处理者,它主要用于发送和处理消息,发送消息一般是使用 Handler 的 sendMessage() 方法,而发出的消息经过一系列的处理后,最后会传到 Handler 的 handMessage() 方法中,我们来看 Handler 中的一个构造方法:
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&