Android消息处理

Android消息处理

 

1、消息:Message的常用属性

what:消息号

//注意:target是default权限,即只有android.os这个packages内才可以访问;

//只能用Hanler.obtainMessage()或Message.obtainMessage (handler,)

target:处理该消息的Handler;

callback:消息的回调

arg1,arg2:默认的int型数据体

 

尽量通过Handler.obtainMessage ()来生成消息。

2、消息队列: MessageQueue

enqueueMessage():向队列发送消息

尽量通过Handler来发送和删除消息。

3、消息循环:Looper

  • Looper组合了ThreadMessageQueue

  • Android的消息循环是针对线程的,但线程可以有消息循环,也可以没有;有消息循环的线程一般都会有一个Looper,并且只能有一个Looper

  • 主线程(UI线程)自带消息循环,所有的应用组件----包括ActivityServiceBroadcast Receiver都在应用程序的主线程中运行。

    Activity启动时,系统会为其创建消息队列和消息循环:通过AcitivityManagerService进程的startActivity>>startProcess,创建用户ProcessActivityThreadActivityThread组合了 LooperHandler的子类H,不展开。

  • 创建的工作线程默认没有消息队列和消息循环,要进行消息处理,有以下2种方式:

    1)为工作线程创建独立的消息循环。

    2)把消息放入主线程的消息队列中,在主线程中处理:因为主线程一般负责视图组件的更新操作,对于不是线程安全的视图组件来说,这种方式能够很好的实现视图的更新。

  • 尽量使用HandlerThread来为工作线程创建消息循环,可以避免线程的同步问题,需特别留意自带消息循环线程的生命周期,不要滥用。

  • 通过Looper.myLooper()可以得到当前线程的Looper对象,通过Looper.getMainLooper()得到当前进程的主线程的Looper对象。

  • 使用Looper已经足够完成向指定线程发送消息的工作:

    1)获取指定线程的Looper对象--mLooper。

    2)定义好Message对象:

        Message msg = Message.obtain();
        msg.what = 1;
        msg.arg1 = 2;
        msg.arg2 = 3;
        msg.target = handler;//目标线程的handler

……

3)直接调用目标线程的消息队列,发送消息:

但这种方式比较繁琐,容易出错,且无法自定义消息的处理回调,因此使用Handler类来简化。

  • mLooper.myQueue.enqueueMessage(msg,0);

  • Looper在loop()循环中处理消息,对每一条消息调用:

    msg.target.dispatchMessage(msg);

target是一个Handler对象,一个Looper可以对应多个Handler,在各自的线程Handler中处理自定义消息。


 

4、工具辅助:Handler

  • Handler运行在创建它的线程中,如果在handleMessage 中进行耗时的操作,会阻塞创建它的线程。

  • Handler应该由处理消息的线程创建:

class LooperThread extends Thread {
    public Handler mHandler;
    
    public void run() {
        Looper.prepare();
    
        mHandler = new Handler() {
            @Override 
            public void handleMessage(Message msg) {
                // process incoming messages here
            }
        };

        Looper.loop();
    }

}

并不意味着每个Handler都需要独立的线程,可以在一个线程中创建多个Handler。常见的例子是在自定义控件中增加Handler来更新UI,这些自定义控件的Handler都将在UI线程创建。

  • 工作线程生成Handler前,务必确保该线程已经建立一个Looper,否则会报错。

    -->Handler 对象构造时,如果不带Looper参数、不在主线程中,则需要先调用Looper.prepare(),以便为工作线程创建独立的消息循环;

    -->Handler 对象构造时,如果是在主线程中(比如在自定义控件中定义的Handler)、不带Looper参数,则代表使用主线程的消息循环;

    -->Handler 对象构造时,带有Looper参数,则代表使用Looper对应的目标线程的消息循环;

  • Looper.loop()后的代码,只会在生成的Looper退出后,才会被调用。

  • Handler对象以目标线程的Looper创建时,那么当调用HandlersendMessage方法,系统就会把消息发送到目标线程的消息队列,在调用handleMessage方法时处理目标线程消息队列中的消息。

  • 注意带消息循环的工作线程的生命周期。

4、几个要点

  • 尽可能的使用Handler来简化代码处理。

  • Looper总是依附于一个Thread,为这个线程开启消息循环,根据队里中每条消息的target派发消息。

    主线程由系统自动创建Looper;

    工作线程需要通过Looper.prepare()手工创建Looper。

    尽量使用HandlerThread来为工作线程创建消息循环,可以避免线程的同步问题。

  • 一个Looper可以对应多个Handler,每一个Handler都可以自定义消息、处理消息,共享同一个消息循环和消息队列;并非每一个Handler都需要启动一个独立的线程(大多情况下也不会)。

  • 发送到队列里的消息必须要指定处理的Handler(通过msg.tagget),调用指定Handler的dispatchMessage() 来处理消息,按照以下优先级:

    如果消息自带callback,则调用callback;

    如果Handler定义了mCallBack,则调用mCallBack;

    调用Handler重载的handleMessage

  • 利用以上特性,可以通过Handler创建特殊的线程队列,定时开启线程。

private Runnable mRunnable = new Runnable() {
    @Override
    public void run() {
        mHandler.postDelayed(this, 1000);

        // do sth here
    }
};
  • Handler运行在创建它的线程中,如果在handleMessage 中进行耗时的操作,会阻塞创建它的线程,所以不要在主线程创建的的handler中进行耗时操作。

5、在工作线程安全的更新UI

Activity.runOnUiThread(Runnable)

View.post(Runnable)

View.postDelayed(Runnable, long)

发送消息给 在UI线程中创建的Handler

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值