Android中的Handler, Looper, MessageQueue和Thread的相互关系

面试常问的一个问题,也是Android里面非常重要、非常基础的一个问题。这篇blog就来简单总结下这个知识点。

Handler类说明 

Handler类用来发送和处理消息(Message)以及和线程的消息队列(MessageQueue)关联的Runnable对象。

Handler是属于主线程的一个工具类。

当你创建一个新的Handler对象,它会和创建它的这个线程/线程的消息队列绑定,从那个时刻开始,它将向这个消息队列传递消息和runnable对象,并且当它们从队列中出来时执行它们。

Handler主要有两种用途:

  1.合理调度安排消息和runnable对象,使它们在将来的某个点被执行。

  2.将一个动作入队安排在非当前线程执行。

使用Handler我通常使用sendMessage()和HandlerMessage()两方法。sendMessage方法允许你入队一个消息对象(Message),包含一个bundle数据,之后将会被Handler的handleMessage(Message)方法所处理。

Handler,Looper和MessageQueue就是简单的三角关系。Looper和MessageQueue一一对应,创建一个Looper的同时,会创建一个MessageQueue。而Handler与它们的关系,只是简单的聚集关系,即Handler里会引用当前线程里的特定Looper和MessageQueue。

Handler传递runnable的例子

public class MainActivity extends AppCompatActivity implements View.OnClickListener {    private TextView textView;    private Button startBtn;    private Button endBtn;    //使用handler首先要创建一个handler    private Handler mHandler=new Handler();    //要用handler来处理多线程可以使用实现Runnable接口,这里先定义该接口    //线程中运行该接口的run函数    Runnable updateRunnable=new Runnable() {        @Override        public void run() {            //线程每次执行时输出"UpdateThread..."文字,且自动换行            textView.append("\nUpdateThread...");            //延时1s后又将线程加入到线程队列中            mHandler.postDelayed(updateRunnable,1000);        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        textView= (TextView) findViewById(R.id.tv_handler);        startBtn= (Button) findViewById(R.id.btn_start);        endBtn= (Button) findViewById(R.id.btn_end);        startBtn.setOnClickListener(this);        endBtn.setOnClickListener(this);    }    @Override    public void onClick(View v) {        switch (v.getId())        {            case R.id.btn_start:                //将线程接口立即加入线程队列中                mHandler.post(updateRunnable);                break;            case R.id.btn_end:                //将接口从线程队列中移除                mHandler.removeCallbacks(updateRunnable);                break;        }    }}

Handler通过handleMessage()和sendMessage()方法来实现进度条展示的例子

public class ProgressHandlerAct extends AppCompatActivity{    private ProgressBar progressBar;    private Button startBtn;    //创建handler,并且执行    private Handler mHandler=new Handler(){        @Override        public void handleMessage(Message msg) {            //显示进度条            progressBar.setProgress(msg.arg1);            //将线程加入到handler的线程队列中            mHandler.post(updateThread);        }    };    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_progress_handler);        progressBar= (ProgressBar) findViewById(R.id.pb);        startBtn= (Button) findViewById(R.id.btn_start);        startBtn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                //设置progressBar可见                progressBar.setVisibility(View.VISIBLE);                //通过上面定义的handler将线程加入handler中                mHandler.post(updateThread);            }        });    }    //handler中添加的runnable线程    Runnable updateThread=new Runnable() {        int i=0;        @Override        public void run() {            i+=10;            //获取上面handler中的message            Message msg=mHandler.obtainMessage();            //将进度条显示的值赋值给消息的arg1参数            msg.arg1=i;            //延时1s            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }            //关键点1,将消息通过handler发送到消息队列中            mHandler.sendMessage(msg);            if(i==100){                mHandler.removeCallbacks(updateThread);            }        }    };}

上面2个例子表面上看handler使用了post方法启动了runnbale,其实启动的线程和activity主线程是同一个线程,因为它只是 运行了线程的run方法,而不是start方法。

今天就简单总结到这里,有时间会继续进行完善。

更多相关文章

  1. android中的多线程基础问题
  2. 从源码分析RxJava在Android里线程切换的实现
  3. Android UI 的更新及其线程模型
  4. Android多线程编程和线程池
  5. Android中的线程状态之AsyncTask详解
  6. 个人对Android消息机制的一点归纳
  7. Android任务、进程、线程的关系

随机推荐

  1. 只要两步,用Python将地址标记在地图上!
  2. Ansible 之 通过yum模块安装软件
  3. 如何面对人生中的逆境?
  4. 火了!开源的Python抢票神器,过年回家就看这
  5. 圣诞节,教你用Python给微信头像添加一个圣
  6. Python 3.9 新特性:任意表达式可作为装饰
  7. 放大招!耗时一个月,早起做了一个Python数据
  8. 这本面试小册,小鹿终于肝熬出来了!
  9. 我用三年的青春,写下了这 230+篇原创文章!
  10. "天才" 是用来唬人的!