关闭

Android Handler (Loop MessageQueue) 解析

160人阅读 评论(0) 收藏 举报

最近在写代码的时候,突然间碰到loop这个东西,所以上网找了一下文件,看到有一个老兄写的还不错,这里当做笔记一样记下来,也分享给大家看看。

1、Handler用途
2、Handler方法简析
3、Handler Loop MessageQueue原理分析  
4、Handler案例代码

1、Handler 用途
 
       Handler主要用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分逐个的在消息队列中将消息取出,然后对消息进行处理,就是发送消息和接收消息不是同步的处理。 这种机制通常用来处理相对耗时比较长的操作。

2、Handler方法简析
    2.1、发送消息   send****
             sendEmptyMessage(int),发送一个空的消息;
        sendMessage(Message),发送消息,消息中可以携带参数;
        sendMessageAtTime(Message, long),未来某一时间点发送消息;
        sendMessageDelayed(Message, long),延时Nms发送消息。
    
   2.2、延迟发送消息post****()
            post(Runnable),提交计划任务马上执行;
  postAtTime(Runnable, long),提交计划任务在未来的时间点执行;
       postDelayed(Runnable, long),提交计划任务延时多少毫秒再执行。


3、Handler消息机制原理分析
       MessageQueue指的是消息队列,存放消息的队列,按照first in first out的规则执行,每个线程()只拥有一个MessageQueue,在创建Looper对象的时候会创建一个MessageQueue对象,每个MessageQueue都会对应一个Handler。
       上面介绍到的handler发送消息的两种方法:send和post发送消息給MessageQueue,按照fifo方式执行
       sendMessage发送的是Message对象,会被Handler的handleMessage()函数处理
       post 发送的是Runnable对象,会自己执行
 
       Message --消息对象, MessageQueue中存放的对象。一个MessageQueue中可以存放多个Message对象,通过Message.obtain()或者Handler.obtainMessage()获取message对象,但是不是直接创建对象,而是先看看消息池中看看有没有可用的Message实例,再用给定参数创建一个Message对象,使用removeMessage()方法将Message从MessageQueue当中移除,顺便将其放回消息队列中。

       消息可以理解成线程和线程之间沟通的信息,后台线程完成一个处理以后需要更新UI,则发送一个Message对象給UI线程,里面包含一些刷新信息

       Looper对象-- 操作MessageQueue的对象
    
       一个Looper对象对应一个MessageQueue,通过Looper.myLooper()可以获取当前线程的Looper对象,Looper从MessageQueue中取出Message然后交给handler的HandleMessage()进行处理,处理完成以后,调用Message.recycle()将其放入消息池中。Looper是每个线程中的MessageQueue操作者,在Android中没有全局的MessageQueue,但是android会自动为UI线程创建一个MessageQueue,但是子线程却不会。所以你调用Looper.getMainLooper()可以得到Looper对象,但是Looper.myLooper()却有可能获得null的Looper对象

      Handler 消息的处理者
      
      Handler负责封装Message对象,然后调用sendMessage()方法将message放入MessageQueue队列中,当这条消息被取出的时候会调用对应的Handler对象的handleMessage()方法进行处理,Handler可以共享一个Looper和MessageQueue

      示例代码:普通线程中handler給UI线程发送消息更新android界面

package com.example.handlertest; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.widget.TextView; public class MainActivity extends Activity { private static final int REFRESH_UI = 1; private TextView tvShow; private MyThreadHandler myThreadHandler; private UIHandler uiHandler; private HandlerThread handlerThread; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); //创建刷新UI的handler对象 uiHandler = new UIHandler(); //创建handler线程 handlerThread = new HandlerThread("spendtimes"); handlerThread.start(); //获取handler线程的消息队列,用于创建我自己的handler myThreadHandler = new MyThreadHandler(handlerThread.getLooper()); //发送一条空消息启动操作,此时消息被发送至线程中的消息队列 myThreadHandler.sendEmptyMessage(1); } private void initView() { tvShow = (TextView) findViewById(R.id.show_res); } class MyThreadHandler extends Handler{ public MyThreadHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { if(msg.what == 1) { //耗时处理操作 try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } StringBuilder sb = new StringBuilder(); sb.append(tvShow.getText().toString()); sb.append(" dealwith thread"); //操作完成以后,调用主线程handler发送刷新消息,此时消息被加入UI线程消息队列,等待被执行 //将处理结果保存到obj对象中,随消息发送出去 Message message = new Message(); message.obj = sb.toString(); message.what = REFRESH_UI; uiHandler.sendMessage(message); } } } class UIHandler extends Handler{ @Override public void handleMessage(Message msg) { if(msg.what == REFRESH_UI) { //从消息中获取返回结果 String res = (String) msg.obj; tvShow.setText(res); } } } }

xml文档如下

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <TextView android:id="@+id/show_res" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="hello_world" /> </RelativeLayout>


上面一段代码实现了在普通线程中处理耗时操作完成以后,然后給UI线程发送消息,然后更新UI界面

其中核心流程如下: 
       首先获取一个线程中的MessageQueue,这里我们采用创建一个ThreadHandler,获取这个线程的MessageQueue队列,然后绑定到我们自定义的MyThreadHandler,此时MyThreadHandler的handleMessage方法都是在线程中处理的,不会卡死主进程,当处理完成以后,我们调用主线程中的uiHandler向UI线程中的MessageQueue中发送结果消息,等到主线程从队列中取出消息进行处理,更新UI界面,这样就完美的处理异步操作

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:166次
    • 积分:3
    • 等级:
    • 排名:千里之外
    • 原创:0篇
    • 转载:1篇
    • 译文:0篇
    • 评论:0条
    文章存档