AKever

导航

Android(1)-Handler Looper Message MessageQueue

一些概念:

 

Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。

Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。

MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。

Looper:一个线程可以产生一个Looper对象,用来管理MessageQueue,它就像一个消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。

多线程的问题:

当我们启动一个Android应用程序的时候,Android会首先开启一个主线程,这个主线程的工作主要就是管理界面中的UI控件,进行事件分发,处理消息响应函数等。但是如果处理一个比较耗时的操作时,比如读取本地大文档,读取网络数据等等时,如果依然用主线程的话,就会出现问题,Android系统规定默认5S无反应的话,就会弹出强制关闭对话框。

在这个时候我们就需要另外开一个线程来处理耗时的工作,这与在学习SurfaceView的时候,我们开启了一个线程去处理频繁更新的操作有些类似。但是因为子线程涉及到UI更新,而更新UI只能在主线程中更新(Android主线程不是线程安全的),子线程中操作是危险的。Handler就是用来解决这个复杂问题而出现的。Handler运行在主线程中(UI线程中),它与子线程可以通过Message对象来传递数据,这个时候,Handler就承担着接受子线程传过来的(子线程用sendMessage()方法传递)Message对象(里面包含数据),把这些消息放入主线程队列中,配合主线程进行更新UI。

如图个人理解机制:

了解Handler与Looper内部源码分析,参考 http://blog.csdn.net/innost/article/details/6055793

下面是简单入门实现:

package com.blueeagle;

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

public class SendMessage extends Activity {
    private TextView textView;
    private MyHandler myHandler;//定义一个自己的Handle类
    private Button button;
    private MyThread m=new MyThread(); //定义一个自己的线程类
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main); 
        textView=(TextView)findViewById(R.id.text);
        button=(Button)findViewById(R.id.startButton); 
        button.setOnClickListener(new View.OnClickListener() { 
          @Override
          public void onClick(View arg0) { 
            myHandler=new MyHandler(); 
            new Thread(m).start(); 
            System.out.println("主线程运行ID:"+Thread.currentThread().getId());
          } 
        });
    }//在对UI进行更新时,执行时所在的线程为主UI线程 
class MyHandler extends Handler{//继承Handler类时,必须重写handleMessage方法 public MyHandler(){ } public MyHandler(Looper l){ super(l); } @Override public void handleMessage(Message msg) {//执行接收到的通知,此时执行的顺序是按照队列进行,即先进先出 super.handleMessage(msg); Bundle b=msg.getData(); String textStr1=b.getString("textStr"); SendMessage.this.textView.setText(textStr1);//更改TextView中的值 } }//该线程将会在单独的线程中运行 class MyThread implements Runnable{ int i=1; @Override public void run() { while(i<11){ System.out.println("当前运行线程ID:"+Thread.currentThread().getId()); try { Thread.sleep(1000); }catch(InterruptedException e){ e.printStackTrace(); } Message msg=new Message(); Bundle b=new Bundle(); b.putString("textStr", "线程运行"+i+"次"); i++; msg.setData(b); SendMessage.this.myHandler.sendMessage(msg);//通过sendMessage向Handler发送更新UI的消息 } i=1;//下次启动线程时重新计数。 } } }

Handler类的四个构造函数中,都会有如下代码:
mQueue = mLooper.mQueue;

Looper类的构造函数如下:

    private Looper() {
        mQueue = new MessageQueue();
        mRun = true;
        mThread = Thread.currentThread();
    }

 

http://blog.csdn.net/L_serein/article/details/6269270

 

Message Queue:

Message Queue是一个消息队列,用来存放通过Handler发布的消息。Android在第一启动程序时会默认会为UI thread创建一个关联的消息队列,可以通过Looper.myQueue()得到当前线程的消息队列,用来管理程序的一些上层组件,activities,broadcast receivers 等等。你可以在自己的子线程中创建Handler与UI thread通讯。  

 

通过Handler你可以发布或者处理一个消息或者是一个Runnable的实例。每个Handler都会与唯一的一个线程以及该线程的消息队列管理。

Looper扮演着一个Handler和消息队列之间通讯桥梁的角色。程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的Handler,Handler接受到消息后调用handleMessage进行处理。

转自:http://blog.csdn.net/jkkjklmn/article/details/7032504

参考:http://blog.csdn.net/android_tutor/article/details/5834246

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

posted on 2013-12-11 11:29  AKever  阅读(376)  评论(0)    收藏  举报