您的位置:首页 > 其它

消息传递机制之Handler机制

2018-02-28 11:14 120 查看

Handler由来

    在项目中, 都会遇见线程之间通信, 组件之间通信.
    在应用程序中,往往会有一些比较耗时的操作 , 为了防止阻塞主线程 , 会将耗时的操作放到子线程中执行 , 处理完成后再去更新UI , 但是android不允许子线程操作UI , 违背了android单线程模型的原则(即UI操作不是线程安全的而且这些操作必须放在UI线程中执行) , 因此android通过Hander消息机制来实现线程之间的通信.

Handler中的主要角色

    


Message: 消息. 消息处理对象以及数据等, 由MessageQueue统一列队 , 终由Handler处理
Handler : 处理者. 负责Message的发送及处理 . 使用Handler时 , 需要实现handleMessage方法
MessageQueue : 消息队列. 用来存放Handler发送过来的消息 , 按照链表的方式串联起来 , 等待Looper的抽取
Looper : 轮询器 . 不断的从MessageQueue中获取Message并执行 .

Handler消息机制解析

Message对象创建Message msg = new Message();
Message msg = Message.obtain();在Handler对象中 , 初始化了两个对象 : Looper , messageQueue . 初始化完成后 , 主线程的中Looper对象已经开始轮询循环的获取消息 , 如果没有消息 , 主线程就会处于休眠状态.public Handler() {
...
// 得到一个主线程的Looper对象
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
// 主线程的消息队列对象
mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}主线程looper的初始化 , 在ActivityThread中的main函数中:public static void main(String[] args) {
//不相关的内容
//初始化Looper
Looper Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
    sMainThreadHandler = thread.getHandler();
}
...
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//开启循环,looper进入一个死循环中不停的取出消息并处理,一旦looper停止,那么我们的应用也就结束
Looper.loop();
//looper停止的话就会走到这里抛出异常
throw new RuntimeException("Main thread loop unexpectedly exited");
}looper类中的loop方法 ,是一个死循环, 它会不停的获取message消息 , 交给handler处理 , 如果没有消息MessageQueue就会阻塞public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
Message msg = queue.next();
...
}
}Handler对象发送消息 , sendMessage方法: public final boolean sendMessage(Message msg) {
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
//把当前Handler对象赋值给Message中的target对象.
msg.target = this;
// 把消息传递给消息队列存起来.
sent = queue.enqueueMessage(msg, uptimeMillis);
}else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
// 此方法是把传递进来的消息按照先后顺序或者时间来进行排序, 并且存起来.
final boolean enqueueMessage(Message msg, long when) {
...
msg.when = when;
//Log.d("MessageQueue", "Enqueing: " + msg);
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
needWake = mBlocked; // new head, might need to wake up
} else {
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
needWake = false; // still waiting on head, no need to wake up
}
...
}当主线程被唤醒 , 会继续执行while循环 , 去消息队列MessageQueue中获取消息public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
while (true) {
// 取出发送的消息.
Message msg = queue.next();
if (msg != null) {
if (msg.target == null) {
return;
}
if (me.mLogging!= null) me.mLogging.println(
">>>>> Dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);
// 因为Message中的target对象就是Handler对象, 这里其实调用的是Handler中的 dispatchMessage方法.
msg.target.dispatchMessage(msg);
if (me.mLogging!= null) me.mLogging.println(
"<<<<< Finished to " + msg.target + " "
+ msg.callback);
msg.recycle();
}
}
}Handler中的dispatchMessage方法public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
// 调用了自己的handleMessage方法.
handleMessage(msg);
}
}

Handler使用

1.发送消息
    在主线程中定义HandlerHandler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
//拿到数据,完成界面更新
tv.setText((String)msg.obj);
break;
}
}
};    子线程发送消息,通知Handler更新UIprivate void getDataFromNet(){
new Thread(){
@Override
public void run() {
//执行耗时操作,完成之后发送消息给Handler,完成UI更新
mHandler.obtainMessage(1,"发送消息").sendToTarget();
}
}.start();
}在线程间发送消息的方法
sendEmptyMessage(int)
sendMessage(message)
obtainMessage(what,obj).sendToTarget()
sendMessageAtTime(message , long)  //在指定时间发送消息
sendMessageDelayed(message, long) //延时发送消息
2. 执行任务
    主线程中定义HandlerHandler mHandler = new Handler();    子线程中提交任务更新UI new Thread(){
@Override
public void run() {
Log.d(TAG,"执行耗时的操作...");
mHandler.post(new Runnable() {
@Override
public void run() {
//main
Log.d(TAG, "线程..." + Thread.currentThread().getName());
//更新UI操作
tv.setText("post执行任务的形式");
}
});
}
}.start();注意: mHandler.post(runable)其实不会新起线程, 只是执行runable中的run()方法, 却没有执行start()方法, 所以runabel执行的UI线程
执行任务的方法
post(runnable)
postAtTime(runnable , long) 在未来的时间点执行任务
postDelayed(runnable,long) 延时ms执行任务

基于Handler机制实现

1.runOnUiThread(Runable) new Thread(new Runnable() {
@Override
public void run() {
//耗时操作,完成之后提交任务更新UI
final String data = "网络数据";
runOnUiThread(new Runnable() {
@Override
public void run() {
        //更新UI,但是不可以执行耗时操作
textView.setText(data);
}
});
}
}).start();    Activity.runOnUiThread(Runnable)将更新UI的代码放在Runnable中 , 然后需要更新UI时 . 再将Runnable对象传给Activity.runOnUiThread(Runable)

2.View.post(Runnable) new Thread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "这里执行耗时的操作...");
tv.post(new Runnable() {
@Override
public void run() {
//这里更新UI
tv.setText("view.post形式");
}
});
}
}).start();3.AsyncTask代替Thread private void getDataFromNet() {
MyTask task = new MyTask();
task.execute();
}

private class MyTask extends AsyncTask {

//后台线程中执行
@Override
protected Object doInBackground(Object... params) {
//执行耗时操作
String data = "网络数据";
return data;
}
//后台线程执行结束后的操作,其中参数result为doInBackground返回的结果
        @Override
protected void onPostExecute(Object result) {
super.onPostExecute(result);
textView.setText((String) result);
}
}以上是本人对于Handler机制的一些理解和看法 , 如果有不对的地方 , 欢迎各位同仁指正.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息