android Handler及消息处理机制的简单介绍

  学习android线程时,直接在UI线程中使用子线程来更新TextView显示的内容,会有如下错误:android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

  大致意思就是:只有创建这个控件的线程才能去更新该控件的内容。

  android中,如果要操作UI,都必须在UI线程,即主线程中去做,我们不能直接在UI线程中去创建子线程来实现,即不能通过这种方式来实现:

new Thread( new Runnable() {
    public void run() {
         textView.setText("update");
     }
}).start();

要想实现更新TextView显示的内容,要利用消息机制:Handler;

消息机制的三个方面,也可以是四个方面:

(1)Looper:一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列);

(2)Handler:使用Handler发送消息对象到消息队列,或者接受Looper从消息队列里取出来的消息;

(3)MessageQueue:用来存放线程放入的消息;

(4)线程:UI Thread通常就是main Thread,而Android启动程序时会替它建立一个MessageQueue;

1.Handler创建消息:

  每一个消息都需要被指定的Handler处理,通过Handler创建消息便可完成此功能。

  Android消息机制中引入了消息池,Handler创建消息时首先查询消息池中是否有消息存在,如果有直接从消息池中取得,如果没有则重新初始化一个消息实例。

  使用消息池的好处是:消息不被使用时,并不作为垃圾回收,而是放入消息池,可供下次Handler创建消息时使用,消息池提高了消息对象的复用,减少系统垃圾回收的次数。

  消息的创建流程如图所示:

2.Handler发送消息

  UI主线程初始化第一个Handler时会通过ThreadLocal创建一个Looper,该Looper与UI主线程一一对应,使用ThreadLocal的目的是保证每一个线程只创建唯一一个Looper,这点可以查看android的源代码;

  之后其他Handler初始化的时候直接获取第一个Handler创建的Looper,而Looper初始化的时候会创建一个消息队列MessageQueue。

  至此,主线程、消息循环、消息队列之间的关系是1:1:1;

  Handler、Looper、MessageQueue的初始化流程如图所示

  而Hander持有对UI主线程消息队列MessageQueue和消息循环Looper的引用,子线程可以通过Handler将消息发送到UI线程的消息队列MessageQueue中;

3.Handler处理消息

  UI主线程通过Looper循环查询消息队列UI_MQ,当发现有消息存在时会将消息从消息队列中取出;

  首先分析消息,通过消息的参数判断该消息对应的Handler,然后将消息分发到指定的Handler进行处理。

  子线程通过Handler、Looper与UI主线程通信的流程如图所示:

下面我们用一个例子来实现更新UI Thread中TextView的内容;

activity_main.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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.xiaozhang.handler1.MainActivity" >

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="@string/hello_world" />

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/textView"
        android:text="button"
        />

</RelativeLayout>

MainActivity.java

package com.xiaozhang.handler1;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {

    private Button button;
    private TextView textView;
    private Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = (Button) findViewById(R.id.button);
        textView = (TextView) findViewById(R.id.textView);
        button.setOnClickListener(new ButtonListener());
        handler = new MyHandler();
    }

    class MyHandler extends Handler {

        @Override
        public void handleMessage(Message msg) {
            textView.setText((String) msg.obj);
        }
    }

    class ButtonListener implements OnClickListener {

        @Override
        public void onClick(View v) {
            Thread t = new MyThread();
            t.start();
        }
    }

    class MyThread extends Thread {
        @Override
        public void run() {
            try {
                Thread.sleep(2 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            String s = "the message from child thread!";
            Message msg = handler.obtainMessage();

            msg.obj = s;
            handler.sendMessage(msg);
        }
    }
}

注:MainActivity中的内部类一般通过匿名内部类来实现;

例如:

package com.xiaozhang.handler1;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {

    private Button button;
    private TextView textView;
    private Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = (Button) findViewById(R.id.button);
        textView = (TextView) findViewById(R.id.textView);
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(2 * 1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        String s = "the message from child thread!";
                        Message msg = handler.obtainMessage();

                        msg.obj = s;
                        handler.sendMessage(msg);
                    }
                }.start();
            }
        });
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                textView.setText((String) msg.obj);
            }
        };
    }
}

我只是随便写了下,应该还可以再进行改进;

显示效果为:

然后点击button,等待2秒后,再次显示为:

文章参考及整理自:

  http://blog.csdn.net/itachi85/article/details/8035333

  Mars视频;

推荐:

http://www.jb51.net/article/33514.htm

时间: 2024-11-09 04:56:19

android Handler及消息处理机制的简单介绍的相关文章

Android Handler 异步消息处理机制的妙用 创建强大的图片加载类

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38476887 ,本文出自[张鸿洋的博客] 最近创建了一个群,方便大家交流,群号:55032675 上一篇博客介绍了Android异步消息处理机制,如果你还不了解,可以看:Android 异步消息处理机制 让你深入理解 Looper.Handler.Message三者关系 .那篇博客的最后,提出可以把异步消息处理机制不仅仅是在MainActivity中更新UI,可以用到别的地方,

Android Handler 异步消息处理机制的妙用 创建强大的图片载入类

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38476887 ,本文出自[张鸿洋的博客] 近期创建了一个群.方便大家交流,群号:55032675 上一篇博客介绍了Android异步消息处理机制.假设你还不了解,能够看:Android 异步消息处理机制 让你深入理解 Looper.Handler.Message三者关系 . 那篇博客的最后,提出能够把异步消息处理机制不仅仅是在MainActivity中更新UI.能够用到别的地方

从Handler+Message+Looper源代码带你分析Android系统的消息处理机制

PS一句:不得不说CSDN同步做的非常烂.还得我花了近1个小时恢复这篇博客. 引言 [转载请注明出处:http://blog.csdn.net/feiduclear_up CSDN 废墟的树] 作为Android开发人员,相信非常多人都使用过Android的Handler类来处理异步任务. 那么Handler类是怎么构成一个异步任务处理机制的呢?这篇 博客带你从源代码分析Android的消息循环处理机制.便于深入的理解. 这里不得不从"一个Bug引发的思考"開始研究Android的消息

从Handler+Message+Looper源码带你分析Android系统的消息处理机制

引言 [转载请注明出处:从Handler+Message+Looper源码带你分析Android系统的消息处理机制 CSDN 废墟的树] 作为Android开发者,相信很多人都使用过Android的Handler类来处理异步任务.那么Handler类是怎么构成一个异步任务处理机制的呢?这篇 博客带你从源码分析Android的消息循环处理机制,便于深入的理解. 这里不得不从"一个Bug引发的思考"开始研究Android的消息循环处理机制.说来话长,在某一次的项目中,原本打算开启一个工作线

Android应用程序消息处理机制(Looper、Handler)分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6817933 Android应用程序是通过消息来驱动的,系统为每一个应用程序维护一个消息队例,应用程序的主线程不断地从这个消息 队例中获取消息(Looper),然后对这些消息进行处理(Handler),这样就实现了通过消息来驱动应用程序的执行,本文将详细分析Android 应用程序的消息处理机制. 前面我们学习Android应用程序中的Activ

Android多线程----异步消息处理机制之Handler详解

关于Android的多线程知识,请参考本人之前的一篇博客:Android 多线程----AsyncTask异步任务详解 在Android当中,提供了异步消息处理机制的两种方式来解决线程之间的通信问题,一种是今天要讲的Handler的机制,还有一种就是之前讲过的 AsyncTask 机制. 一.handler的引入: 我们都知道,Android UI是线程不安全的,如果在子线程中尝试进行UI操作,程序就有可能会崩溃.相信大家在日常的工作当中都会经常遇到这个问题,解决的方案应该也是早已烂熟于心,即创

深入源码分析Handler的消息处理机制

学习Android的同学注意了!!! 学习过程中遇到什么问题或者想获取学习资源的话,欢迎加入Android学习交流群,群号码:364595326  我们一起学Android! handler的消息处理有三个核心类:Looper,Handler和Message.其实还有一个Message Queue(消息队列),但是MessageQueue被封装到Looper里面了,我们不会直接与MessageQueue打交道,因此我没将其作为核心类.下面一一介绍: 线程的魔法师Looper Looper的字面意

Android Handler AsyncTask 消息机制

一.Android消息机制一 Android 有一种叫消息队列的说法,这里我们可以这样理解:假如一个隧道就是一个消息队列,那么里面的每一部汽车就是一个一个消息,这里我们先忽略掉超车等种种因素,只那么先进隧道的车将会先出,这个机制跟我们android 的消息机制是一样的. 角色描述 1. Looper:(相当于隧道) 一个线程可以产生一个Looper 对象,由它来管理此线程里的Message Queue( 车队,消息隧道) . 2. Handler: 你可以构造Handler 对象来与Looper

Android多线程——异步消息处理机制

Android中的异步消息处理机制主要由四个部分组成,Message.Handler.MessageQueueh和Looper.这里先简要介绍一下四个部分. 1.Message Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据,Message可以使用what.arg1和arg2字段来携带一些整形数据.使用obj来携带一个Object对象. 2.Handler Handler是处理者的意思,主要用于发送和处理消息.发送消息一般是使用Handler的sen