Android 的消息机制
在android 中,我们通常把UI页面所在的线程叫做主线程,如果主线程执行某一项耗时操作超过5秒中,程序就会报ANR异常。到那时我们在实际开发的过程中,不可避免的会进行耗时操作,比如加载网络图片,加载网络数据等,此时我们通常会将耗时操作放在子线程中执行,子线程执行完成后剑门关数据或结果发送给主线程,这个时候就用到了android 的消息机制。
消息队列
Android应用程序每启动一个线程,都为其创建一个消息队列,然后进入到一个无线循环之中,然后不断检查队列中是否有新消息需要处理,如果没有,线程就会进入睡眠状态,繁殖会对消息进行分发处理。
消息机制的核心类
android 的消息处理有三个核心类:Looper,Handler和Message。(消息队列被封装到Looper里面,我们不会直接与消息队列打交道)。
消息(Message):存放在消息队列中,被Looper循环取出执行,消息可以携带数据,并制定操作;
Handler:可以向消息队列中存放消息;
Looper:无线循环地从消息队列中获取消息并执行。
(1)Message类
android.os.Message的主要功能是进行消息的封装,并且同时可以指定消息的操作形式。
No. | 变量或方法 | 类型 | 描述 |
1 | public int what | 变量 | 用于定义此Message属于何种操作 |
2 | public Object obj | 变量 | 用于定义此Message传递的信息数据 |
3 | public int arg1 | 变量 | 传递一些整型数据时使用,一般很少使用 |
4 | public int arg2 | 变量 | 传递一些整型数据时使用,一般很少使用 |
5 | public Handler getTarget() | 普通 | 取得操作此消息的Handler对象 |
(2)Handler类常用方法
Message对象封装了所有的消息,而这些消息的操作就需要android.os.Handler类完成
No. | 方法 | 类型 | 描述 |
1 | public Handler() | 构造 | 创建一个新的Handler实例 |
2 | public Handler(Looper looper) | 构造 | 使用指定的队列创建一个新的Handler实例 |
3 | public final Message obtainMessage(int what, Object obj) | 普通 | 获得一个Message对象 |
4 | public final Message obtainMessage(int what, int arg1, int arg2, Object obj) | 普通 | 获得一个Message对象 |
5 | public void handleMessage(Message msg) | 普通 | 处理消息的方法,子类要覆写此方法 |
6 | public final boolean hasMessages(int what) | 普通 | 判断是否有指定的Message |
7 | public final boolean hasMessages(int what, Object object) | 普通 | 判断是否有指定的Message |
8 | public final void removeMessages(int what) | 普通 | 删除掉指定的Message |
9 | public final void removeMessages(int what, Object object) | 普通 | 删除掉指定的Message |
10 | public final boolean sendEmptyMessage(int what) | 普通 | 发送一个空消息 |
11 | public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) | 普通 | 在指定的日期时间发送消息 |
12 | public final boolean sendEmptyMessageDelayed(int what, long delayMillis) | 普通 | 等待指定的时间之后发送消息 |
13 | public final boolean sendMessage(Message msg) | 普通 | 发送消息 |
(3)Handler的使用
通过Handler对象我们可以封装Message对象,然后通过sendMessage(msg)把Message对象添加到消息队列中;
当MessageQueue(消息队列)循环到该Message时,就会调用该Message对象对应的handler对象的handleMessage()方法对其进行处理;
由于是在handleMessage()方法中处理消息,因此我们需要编写一个类继承Handler,然后重写handleMessage()处理我们需要的操作。
class MyHandler extends Handler {
@Override public void handleMessage(Message msg) {
// 操作 } }
实例:
实现计时器功能
package com.zhidi.clock;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
//1、定义一个what标记、一个Handler对象,一个初始为10的int数据。
public static final int WHAT_MAIN = 1;
private Handler mainHandler;
private int count=10;
private Button bt_start;
private TextView tv_show;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
//4、实例化主线程的Handler
mainHandler = new MyHandler();
bt_start.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
//5、启动子线程。
new Thread(new ChildThread()).start();
}
});
}
private void init(){
bt_start=(Button)findViewById(R.id.bt_start);
tv_show=(TextView)findViewById(R.id.tv_show);
}
/**
* 2、创建一个子线程类,extends Thread,重写run()实现倒数计数器,并把Message传递给主线程。
* @author Administrator
*/
class ChildThread extends Thread{
@Override
public void run() {
Looper.prepare();// 初始化Looper
//实现倒数计数器
while(count>=0){
try {
Message toMain = mainHandler.obtainMessage();// 创建Message
toMain.obj = count;//设置显示文字
toMain.what = WHAT_MAIN; //设置主线程操作的状态码
mainHandler.sendMessage(toMain);
count--;
Thread.sleep(1000);// 延迟1秒
} catch (Exception e) {
}
}
Looper.loop();//启动该线程的消息队列
}
}
/**
* 3、创建一个自定义Handler类,extends Handler,重写handleMessage(Message),判断what标记更新UI。
* @author Administrator
*
*/
class MyHandler extends Handler{
@Override
public void handleMessage(Message msg) {
switch (msg.what) {//判断what操作
case WHAT_MAIN:// 设置主线程的操作类
tv_show.setText(msg.obj.toString());//设置文本内容
break;
}
}
}
}