Android消息机制

老生常谈了,我们所说Android的消息机制,其实就是Android中的Handle机制,主要用来解决的问题就是Android中不能在子线程中更新UI。其标志性的用法如下:

public class TestActivity extends Activity {
  private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {  //处理或查看消息
            super.handleMessage(msg);
            System.out.println(msg.what);
        }
    };
    @Override
    public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        setContentView(R.layout.activity_main);
        new Thread(new Runnable() {
            @Override
            public void run() {
                //耗时操作
                Message message = Message.obtain();
                message.what = 1;
                mHandler.sendMessage(message);
            }
        }).start();
    }
}

上述代码大致是这样一个过程: 在主线程中创建Handle实例,并重写handleMessage方法用来接收和处理消息。另开启一个线程来进行比较耗时的操作,操作完成后将数据传递给Message对像,然后通过Handle来发送消息。Handle接收到消息之后,对消息进行分析并做出相应的处理,即更新UI。

延伸并十分值得注意的一点:Activity,Service都是运行在主线程中,所以在这两个组件中都不能进行耗时操作,否则会报ANR(应用无响应)的异常。一般的耗时操作需使用Android提供的AsyncTask,或者开启新的线程来处理。

下面对消息机制进行分析:

概述:Android的消息机制主要是指Handle的运行机制及Handle所关联的MessageQueue与loop的工作过程。

Handle分为四个部分:Handle,Message,MessageQueue,loop。下面详细介绍这四个部分,首先上图(消息机制的整体架构图)


Handle:消息辅助类,主要功能向消息池发送各种消息事件(Handler.sendMessage)和处理相应消息事件(Handler.handleMessage)。包含Looper和MessageQueue,dispatchMessage()用来分发消息。发送消息的方式有两种,post()与sendMessage()。

Message:需要传递的消息,可以传递数据,并记录发送和处理消息的Handler。

MessageQueue:消息队列,其内部实现并不是用的队列,实际上是通过一个单链表的数据结构来维护消息列表,因为单链表在插入和删除上比较有优势。主要功能向消息池投递消息(MessageQueue.enqueueMessage)和取走消息池的消息(MessageQueue.next)。主要是维护一组待处理的消息。

Loop:其中包含一个消息队列(MessageQueue),不断循环(Looper.loop),从MessageQueue中读取消息,按分发机制将消息分发给目标处理者。

接下来说一下消息机制的运行流程:


在子线程执行完耗时操作,当Handler发送消息时,将会调用MessageQueue.enqueueMessage,向消息队列中添加消息。当通过Looper.loop开启循环后,会不断地从线程池中读取消息,即调用MessageQueue.next,然后调用目标Handler(即发送该消息的Handler)的dispatchMessage方法传递消息,然后返回到Handler所在线程,目标Handler收到消息,调用handleMessage方法,接收消息,处理消息。

MessageQueue,Handler和Looper三者之间的关系:

每个线程中只能存在一个Looper,Looper是保存在ThreadLocal中的。主线程(UI线程,ActivityThread)已经创建了一个Looper,所以在主线程中不需要再创建Looper,但是在其他线程中需要创建Looper(looper.prepare())。每个线程中可以有多个Handler,即一个Looper可以处理来自多个Handler的消息。 Looper中维护一个MessageQueue,来维护消息队列,消息队列中的Message可以来自不同的Handler。在loop中,当next()取出下一条消息时,队列中已经没有消息时,next()会无限循环,产生阻塞,等待MessageQueue中加入消息,然后重新唤醒。

那我们如何获取到当前线程呢? Looper是保存在ThreadLocal中的,所以当然是从ThreadLocal中获取了。ThreadLocal是线程本地存储区(Thread Local Storage,简称为TLS),它并不是线程,而是用来在每个线程中保存数据,而且在不同的线程中数据互不干扰。这样,我们就能很方便的获取当前线程的loop对象了。

以上,就是Handle的知识点了。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值