Handler消息传递机制

一、Handler消息传递机制的产生原因

         出于对性能优化的考虑,致使Android不是线程安全的。如果多个线程并发操作UI组件,会产生线程安全问题。为此,Android制定了一个规则:只允许在UI线程中操作UI组件。但是,试想一下,如果我们创建了一个子线程,在子线程中执行了一个任务,这个任务涉及到要操作UI组件,但由于规则的限制,我们不能直接在子线程中操作UI组件。就在这种情况下,我们的Handler消息传递机制应运而生了。通过它,我们可以发送消息来更新UI线程中的UI组件

二、Handler类简介

       Hanlder有两个主要作用:

       1、在新启动的线程中发送消息  

       2、在UI线程中接收并处理消息

三、Handler消息传递机制的工作原理

       为了更好的理解Handler的工作原理,我们得先来了解一下与Handler一起工作的几个组件。

        1、Message:Handler发送、接受并处理的消息对象

        2、Looper:每个线程只能有一个Looper对象。它的Loop方法负责从MessageQueue循环读取Messsage对象,并将读取的Message对象交给发送该消息的Handler处理

        3、MessageQueue:消息队列,用来存放Message对象的,采用先进先出的方式来管理Message对象。程序创建Looper对象时会在他的构造器中创建MessageQueue对  象。Looper提供的构造器源代码如下:

        private Looper() {

          mQueue = new MessageQueue();

          mRun  = true;

          mThread = Thread.currentThread();

        }

该构造器使用了private修饰,表明程序员无法通过构造器创建Looper对象。从上面代码不难看出,程序在初始化Looper时会创建一个与之关联的MessageQueue,这个MessageQueue就负责管理消息。

各个组件之间的关系如下图所示


四、Looper对象的分类情况

      第一种情况:主UI线程中,系统已经初始化了一个Looper对象,因此程序直接创建Handler即可,然后就可通过Handler来发送消息、处理消息。

      第二种情况:程序员自己启动的子线程,程序员必须自己创建一个Looper对象,并启动它。创建Looper对象调用它的prepare()方法即可。然后调用Looper的静态loop()方法来启动它。

五、使用Handler的步骤

        第一种情况的步骤就不说了,下面是一个显示当前时间的一个栗子,代码如下:

package com.river.test.handlerdemo;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

  private TextView mTextView;
 public static final int MSG = 0;
  Timer mTimer = new Timer();
  private Handler myHandler = new Handler(){
    @Override public void handleMessage(Message msg) {
      if(msg.what==MSG) {
        Log.d("TAG", msg.obj.toString());
          mTextView.setText( msg.obj.toString());
      }
    }
  };
  TimerTask mTask = new TimerTask() {
    @Override public void run() {
      long time = System.currentTimeMillis();
      SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      Date date = new Date(time);
      String timeStr= simpleDateFormat.format(date);
      Message message = new Message();
      message.what = MSG;
      message.obj = timeStr;
      myHandler.sendMessage(message);
    }
  };
  @Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.looper_layout);
    mTextView = (TextView) findViewById(R.id.tv_show);
    mTimer.schedule(mTask,1000,1000);

  }
  @Override protected void onStop() {
    super.onStop();
    mTask.cancel();
    mTimer.cancel();
  }
}

程序运行结果如下图:


第二种情况的使用步骤:

        1、调用Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会创建与之配套的MessageQueue。

        2、有了Looper之后,创建Handler子类的实例,重写handleMessage()方法,该方法负责处理来自于其他线程的消息。

        3、调用Looper的loop()方法启动Looper。

下面的栗子与上面不同的是:handler是在子线程上创建的,具体不同看如下代码示例:

package com.river.test.handlerdemo;

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

public class LooperActivity extends AppCompatActivity {
  private Handler myHandler;
  private Button startBtn;
 public static final int MSG = 0;
  @Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.looper_layout);
    startBtn = (Button) findViewById(R.id.btn_start);
    startBtn.setOnClickListener(new View.OnClickListener() {
      @Override public void onClick(View v) {
        String name = "Hello,World";
        myHandler.obtainMessage(MSG,name).sendToTarget();
      }
    });
    new MyThread().start();
  }

  class MyThread extends Thread{
    @Override public void run() {
       Looper.prepare();//初始化Looper
      myHandler = new Handler(){//绑定handler到MyThread实例的Looper对象
        @Override public void handleMessage(Message msg) {//重写Handler处理消息的方法
            if(msg.what==MSG) {
              Log.d("TAG",msg.obj.toString());
            }

        }
      };
      Looper.loop();//启动消息循环
    }
  }

}

输出结果如下图:

 

 

参考书籍《疯狂Android讲义》

本博客只做学习记录和分享交流,不做他用,如有侵权请联系博主删除。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值