下面我们就来讲解Handler的简单使用,我们实现一个模拟下载过程的操作,并将下载进度更新到进度条和TextView中,那么事不宜迟,我们马上开始。

我们先来总结下使用Handler的步骤:

  1. 创建Hanlder对象,并在handleMessage方法中完成逻辑代码
  2. 创建子线程,在子线程中创建Message对象,使用handler.post方法将消息发送给消息队列(MessageQueue)
  3. handler收到消息,并调用handleMessage方法完成通信(本质上是Looper轮询从MessageQueue中取出消息,并将其发送给Message的target,也就是发送给了handler)

创建Handler对象

上代码:

/**
 * 第一步,主线程中创建Handler并在handleMessage方法中处理相应逻辑
 */
 private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        //这里完成更新UI的操作
        //do something
    }
};

Handler的创建还有其他的方法,比如传入一个Callback对象的构造方法等等,不一而论, 这里handleMessage方法主要是用来处理子线程中传递出来的消息

创建子线程

Android中创建子线程的方法有很多,我这里使用了一种最常见的方法:

//创建子线程
downloadThread = new Thread(new Runnable() {
    @Override
    public void run() {
        //线程结束标志,activity销毁后不再执行线程内代码
        if(!destroyThread) {
            //do something
            for(int i = 0;i < 100;i++) {
                progress++;
                //模拟耗时操作
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Message message = Message.obtain();
                message.what = MESSAGE_WHAT_UPDATE_PROGRESS;
                message.obj = progress;
                handler.sendMessage(message);
            }
        }
    }
});

可以看到上述代码中,主要是模拟了耗时操作,每100ms发出一次消息,消息体中what主要用于区分消息类型,obj携带消息内容,最后调用handler.sendMessage方法将其发出。其中Message的初始化有多种方式,常用的有三种:

  • new Message();
  • Message.obtain();
  • Handler.obtainMessage();

其中我们经常使用的是后两者,而不推荐使用前者,这主要是因为,后两者是从一个可回收的对象池中获取Message对象,比重新new一个Message对象性能更好。

Handler对象处理消息

Looper取到消息后会根据Message的target对象将消息发送给相应的Handler(hander.sendMessage方法会将自身设为该Message的target),然后调用handlerMessage进行处理:

handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        //这里完成更新UI的操作
        if(msg != null && msg.what == MESSAGE_WHAT_UPDATE_PROGRESS) {
            int progress = (int) msg.obj;
            String value = "";
            if(progress <= MAX_PROGRESS) {
                progressBar.setProgress(progress);
                value += "第一进度条:"+progress+"%";
            }
            if(progress*2 <= MAX_PROGRESS) {
                progressBar.setSecondaryProgress(progress*2);
                value += " 第二进度条:"+progress*2+"%";
            } else {
                value += " 第二进度条:"+MAX_PROGRESS+"%";
            }
            tvProgressValue.setText(value);
        }
    }
};

整个Handler的使用流程就是这样了,下面是demo的执行画面:


模拟下载进度条demo

这里就是一个完整的Handler使用的流程了,其中涉及到了一些名词,如Message、MessageQueue、Looper等,我们会在后面详解Hanlder中进行讲解,那么这篇文章就到这里,接下来敬请期待~