欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Handler的理解、用法以及运行机制原理

程序员文章站 2022-06-30 12:30:17
...

一、Handler是什么?

Handler在我们android开发中是一项非常重要的机制,那Handler是什么呢?Handlerandroid提供用于更新UI的一套机制,也是消息处理机制。

Handler的主要作用有两个:

        (1).在新启动的线程中发送消息

                    (2).在主线程中获取,处理消息。

解释:(1) 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件, 进行事件分发, 比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。 主线程(UI线程)就是android程序从启动运行到最后的程序。

(2) 如果此时需要一个耗时的操作,例如: 联网读取数据,或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,会收到Android系统的一个错误提示  "强制关闭"。

(3)这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,Android主线程是线程不安全的, 也就是说,更新UI只能在主线程中更新,子线程中操作是危险的。

(4)这个时候,Handler就出现了。,来解决这个复杂的问题 ,由于Handler运行在主线程中(UI线程中),  它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sendMessage()方法传弟)Message对象(里面包含数据)  , 把这些消息放入主线程队列中,配合主线程进行更新UI。

二、为什么要用Handler

如果我们不用Handler去发送消息,更新UI可以吗?

答案是不行的。 Android在设计的时候,就封装了一套消息创建,传递,处理机制,如果不遵循这样的机制,就没有办法更新UI信息的,就会抛出异常信息。

抛出异常的描述:不能在非UI线程中去更新UI

三、 Handler怎么用

 handler可以分发Message对象和Runnable对象到主线程中,每个Handler实例,都会绑定到创建他的线程中(一般是位于主程),它有两个作用:

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

        (2)安排一个动作在不同的线程中执行

Handler中开启线程和分发消息的一些方法:

      post(Runnable)直接开启Runnable线程

      postAtTime(Runnable,long)在指定的时间long,开始启动线程

      postDelayed(Runnable long)在延迟long时间后,启动Runnable线程

      sendEmptyMessage(int) 发送指定的消息,通过参数int来区分不同的消息

      sendMessage(Message)发送消息到UI线程中

      sendMessageAtTime(Messagelong)     这个long代表的是系统时间,不推荐用

     sendMessageDelayed(Messagelong)    此方法long代表调用后几秒后执行。

   sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.

handler基本使用: 1)在主线程中,使用handler很简单,new一个Handler对象实现其handleMessage方法, handleMessage 中提供收到消息后相应的处理方法即可。(接收消息,并且更新UI

                     2)在新启动的线程中发送消息

示例:

public class HandlerActivity extends AppCompatActivity {

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            tv.setText("msg.arg1:"+msg.arg1+"--msg.arg2:"+msg.arg2);
        }
    };
    private TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler);
        initView();
        new Thread(new Runnable() {
            @Override
            public void run() {
                Message msg = new Message();//实例化消息对象
                msg.arg1 = 99;//携带参数
                msg.arg2 = 100;//携带参数
                Object str = new Object();//实例化对象
                msg.obj = str; //携带参数为实体类对象
            }
        });
        }
    private void initView() {
        tv = (TextView) findViewById(R.id.tv);
    }
}

handler运行机制:

Handler的理解、用法以及运行机制原理 

 

 Handler机制也可叫异步消息机制,它主要由4个部分组成:Message,Handler,MessageQueue,Looper,在上面图中我们已经有了大致印象,接下来我们对4个成员进行着重的了解:

1.Message
  Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。使用Message的arg1和arg2便可携带int数据,使用obj便可携带Object类型数据。

2.Handler
  Handler顾名思义就是处理者的意思,它只要用于在子线程发送消息对象Message,在UI线程处理消息对象Message,在子线程调用sendMessage方法发送消息对象Message,而发送的消息经过一系列地辗转之后最终会被传递到Handler的handleMessage方法中,最终在handleMessage方法中消息对象Message被处理。

3.MessageQueue
  MessageQueue就是消息队列的意思,它只要用于存放所有通过Handler发送过来的消息。这部分消息会一直存放于消息队列当中,等待被处理。每个线程中只会有一个MessageQueue对象,请牢记这句话。其实从字面上就可以看出,MessageQueue底层数据结构是队列,而且这个队列只存放Message对象。

4.Looper
  Looper是每个线程中的MessageQueue的管家,调用Looper的loop()方法后,就会进入到一个无限循环当中,然后每当MesssageQueue中存在一条消息,Looper就会将这条消息取出,并将它传递到Handler的handleMessage()方法中。每个线程只有一个Looper对象。

  了解了上述Handler机制的4个成员后,我们再来把思路理一遍:首先在UI线程我们创建了一个Handler实例对象,无论是匿名内部类还是自定义类生成的Handler实例对象,我们都需要对handleMessage方法进行重写,在handleMessage方法中我们可以通过参数msg来写接受消息过后UIi线程的逻辑处理,接着我们创建子线程,在子线程中需要更新UI的时候,新建一个Message对象,并且将消息的数据记录在这个消息对象Message的内部,比如arg1,arg2,obj等,然后通过前面的Handler实例对象调用sendMessge方法把这个Message实例对象发送出去,之后这个消息会被存放于MessageQueue中等待被处理,此时MessageQueue的管家Looper正在不停的把MessageQueue存在的消息取出来,通过回调dispatchMessage方法将消息传递给Handler的handleMessage方法,最终前面提到的消息会被Looper从MessageQueue中取出来传递给handleMessage方法,最终得到处理。这就是Handler机制整个的工作流程。应该都差不多懂了吧,感觉我写的很接地气啊。

后面有时间再开一篇源码篇深入了解异步处理机制。

 

相关标签: Android理论