Android线程间通讯 Handler学习

线程间通讯所需要的五个类:

1.Message 存放 消息id,消息对应数据-->由MessageQueue统一队列-->最终由Handler处理

2.Handler 处理者 -->Message发送及处理     使用时要实现handleMessage(Message msg)
对特定Message处理  更新UI

3.MessageQueue 存放Handler发送的消息队列,按照FIFO(先进先出)规则执
4.Looper 消息泵 不断从MessageQueue中抽取Message
一个MessageQueue需要一个Looper,一一对应关系
5.Thread 调度整个消息 消息循环执行场所

简单原理解析

  • 生成 
Message msg = mHandler.obtainMessage();
msg.what = what;
msg.sendToTarget();

 

  • 发送
MessageQueue queue = mQueue;
if(queue!=null){
    msg.target = this;
    sent = queue.enqueueMessage(msg,uptimeMillis);
}


Handler.java sendMessageAtTime(Message msg,long uptimeMillis)
找到它所引用的MessageQueue  然后将Message target设置成自己
为了在处理消息环节,Message 能找到正确Handler,再将这个Message纳入消息队列中

  • 抽取
Looper me = myLooper();
MessageQueue queue  = me.mQueue;
while(true){
    Message msg = queue.next();//might block
    if(msg!=null){
        //No target is a magic identifier for the quit message
        return;
    }
    msg.target.dispatchMessage(msg);
    msg.recycle(); //回收
}


Looper.java  loop()函数 死循环,不断从MessageQueue中获取下一个Message(next()方法)
通过Message中携带的target 信息 交由正确的Handler处理(dispatchMessage方法)

  • 处理 
if(msg.callback!=null){
    handleCallback(msg);
}else{
    if(mCallback !=null){
        if(mCallback.handleMessage(msg)){
            
         return;
        }
    }
    handleMessage(msg);
}


Handler.java dispatchMessage(Message msg)方法中,
其中一个分支 调用handleMessage 处理这条Message
所以使用Handler 时 需要实现handleMessage(Message msg)

Message由Handler发送 -->MessageQueue 入队
Looper抽取-->回到Handler同步操作-->异步

-Handler 、Looper、MessageQueue三角关系

Handler与Looper、MessageQueue简单聚集关系
多个Handler可以共用一个Looper MessageQueue 但是Handler就运行在同一个线程中了

通常Handler写法

class LooperThread extends Thread{
	public Handler mHandler;
	public void run(){
		Looper.prepare();//1.创建handler前 为其准备好一个Looper
		mHandler = new Handler(){
			public void handlerMessage(Message msg){
				//process incoming messages here
			}
		}
		Looper.loop();//2.Looper跑起来 抽取Message  这样才能正常操作
	}
}

-Handler 处理消息总是在创建Handler的线程里运行

其他线程访问UI线程方法
1.Activity.runOnUiThread(Runnable r)
2.View.post(Runnable r)//此方法中view获得当前线程的handler 一般UI线程 
将action对象post到-->Handler里,在Handler中将传递来的 Action对象包装成Message,
将其投入UI线程消息循环中    Handler再次处理 消息循环时 有一个分支为他所设的
直接调用Runnable 的run方法    此时已经路由到UI线程里 所以可以处理UI了
3.View.postDelayed(Runnable r,long t);
4.Handler

案例:简单 主线程 子线程通讯

主线程的字符串-->子线程-->字符串进行拼接----回传-->主线程 显示在TextView中

package com.qiuxf.handler;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    private TextView tv_show;
    private Button btn_start;
    private Handler mMainHandler;
    private Handler mChildHandler;
    public static final String TAG = "TAG";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_show = findViewById(R.id.tv_show);
        btn_start = findViewById(R.id.btn_start);
        mMainHandler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                String fromChileString = (String) msg.obj;
                tv_show.setText(fromChileString);
            }
        };
        btn_start.setOnClickListener(new View.OnClickListener() {//主线程与子线程通讯
            @Override
            public void onClick(View v) {
                if(mChildHandler!=null){
                    Message msg = new Message();
                    msg.obj = "from UI";
                    mChildHandler.sendMessage(msg);
                }
            }
        });
        new ChildThread().start();
    }
    private class ChildThread extends Thread{

        @Override
        public void run() {
            Looper.prepare();//初始化消息队列所需要的资源和参数
            mChildHandler = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    String fromUIStr = (String) msg.obj;
                    Log.d(TAG,"接收到UI:"+fromUIStr);
                    String toUIStr = fromUIStr + "-->I'm child";
                    Message msg2UI = new Message();
                    msg2UI.obj = toUIStr;
                    if(mMainHandler!=null){
                        mMainHandler .sendMessage(msg2UI);
                    }
                }
            };
            Looper.loop();//开启消息队列
        }
    }
}

运行结果:

--案例来源于慕课网

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值