`
1140566087
  • 浏览: 547647 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
博客专栏
2c4ae07c-10c2-3bb0-a106-d91fe0a10f37
c/c++ 入门笔记
浏览量:18075
3161ba8d-c410-3ef9-871c-3e48524c5263
Android 学习笔记
浏览量:309467
Group-logo
J2ME 基础学习课程集
浏览量:17989
A98a97d4-eb03-3faf-af96-c7c28f709feb
Spring 学习过程记录...
浏览量:17195
社区版块
存档分类
最新评论

Android 之 Looper Handler Message 之间的关系

阅读更多
       Android 的消息处理机制 -- Looper,Hander,Message

1、Android的消息处理有三个核心类:Lopper,Handler和Message; 另外还有个 Message Queue (消息队列) , 但MQ 被封装到了Looper 里面了,所以不会直接的和MQ打交道,因此不是核心的类;

2、线程的魔法师Looper:Looper 的字面意思是"循环者" ,被设计来使一个普通线程变成Lopper 线程。即循环工作的线程。循环线程,一个线程不断的循环,一旦有了新的任务则执行,执行完继续等待下一个任务,这就是Looper线程;


Looper 的加深理解:
    A、Looper 线程就是循环工作的线程;
    B、一个Thread只能有一个Looper对象,它是一个ThreadLocal;
    C、一个线程可以有多个Handler,但是只能有一个Looper


3、如何创建一个Looper 线程:

/**
 * 创建一个循环线程
 * @author Administrator
 * 线程,继承了Thread 
 */
public class LooperThread extends Thread {

    public void run() {
        // 将当前的线程初始化为Looper线程
        Looper.prepare();
        
        //......
        
        // Looper 开始工作,调用loop() 方法,
        // 不断的从自己的MQ中取出队头的消息(任务)执行
        Looper.loop(); // 开始循环线程
    }
}


通过以上的核心代码,当前的线程就可以升级为Looper线程了;


4、Looper 类的介绍:
    除了prepare() 和 loop() 方法,Looper 类还提供了一些有用的方法:
   
    Looper.myLooper(); // 得到当前线程Looper对象;
    public static final Looper myLooper(){
        // 在任意线程调用Looper.myLooper() 返回的都是那个线程的Looper
        return (Looper)sThreadLocal.get();
    }

    getThread() 得到looper对象所属线程;
    public Thread getThread(){
        return mThread;
    }

    quit(); 方法结束looper循环;
    public void quit(){
        // 创建一个空的message, 它的target为null,表示结束循环消息
        Message msg = Message.obtain();
        //发出消息
        mQueue.enqueueMessage(msg,0);
    }

5、Looper的总结:
    a、每个线程有且最多只能有一个Looper对象,它是一个ThreadLocal;
    b、Looper内部有一个消息队列,loop() 方法调用后线程开始不断从队列中取出消息执行;
    c、Looper使一个线程变成Looper线程;

6、Handler的理解:
    异步处理大神,handler扮演了往MQ上添加消息和处理消息的角色(只处理由自己发出的消息),即通知MQ它要执行一个任务(sendMessage),并在loop到自己的时候执行该任务(handleMessage),整个过程是异步的。handler创建时会关联到一个looper,默认的构造方法将关联当前线程的looper,不过这也是可以set的;

    温习提示:  post发出的Runnable对象最后都被封装成了Message对象;
                handleMessage(Message msg);为"钩子方法";
                android 中的主线程也是一个looper线程;

7、Handler的用处:
    A、可以在任意线程中发送消息,这些消息会被添加到关联的MQ上。
    B、handler是在它关联的looper线程中处理消息的;

8、案例:线程之间进行消息的传递,主线程发消息给自己
    注意:这里使用static修饰,因为在项目中便于单元测试,可以自行设计;


  
 private static Handler handler; // 消息处理

    /**
     * 测试:主线程发消息给自己
     */
    public static void toOwn() {

        // 得到主线程的Looper对象
        Looper looper = Looper.getMainLooper();

        // 根据主线程的looper创建handler,所以这个handler发送的Message
        // 会被传递给主线程的MessageQueue(消息队列)
        handler = new Handler(looper) {
            
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Log.i("msg", "我是主线程,执行收到的消息:"+msg.obj.toString());
            }
        };
        
        //
        handler.removeMessages(0); // 移除
        //提示:通过Message.obtain()来从消息池中获得空消息对象
        // 以便节约资源
        Message msg = handler.obtainMessage(1, 1, 1, "来自主线程的消息");
        handler.sendMessage(msg); // 发送消息
    }

    

    /*   ---------------- 主线程发消息给子线程 -------------------     */
        /**
     * 测试:主线程发消息给子线程
     */
    public static void mainToChild(){
        
        // 创建一个线程
        thread = new Thread(new Runnable() {
            // 线程任务 
            public void run() {
                Log.i("msg", "子线程启动...");
                Looper.prepare();// 创建该线程的Looper对象,用于接收消息
                handler2_1 = new MyHandler(Looper.myLooper());
                Log.i("msg", "对象创建完成");
                Looper.loop();
            }
        });
        thread.start(); // 启动线程
        
        // 根据主线程的Looper对象创建Handler
        handler2 = new Handler(Looper.getMainLooper()){
            
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Log.i("msg", "我是主线程的Handler,收到消息:"+msg.obj.toString());
                
                // 此处 主线程可以将数据给子线程
                handler2_1 = new MyHandler(Looper.myLooper());
                Message msg2 = handler2_1.obtainMessage(1, 1, 1, "主传子");
                handler2_1.sendMessage(msg2);
            }
        };
        Message msg = handler2.obtainMessage(1, 1,1,"主线程进来了,开始分发数据");
        handler2.sendMessage(msg); // 发送消息队列
    }


   子线程数据处理类:
   public class MyHandler extends Handler {

    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        Log.i("msg","我是子线程,收到消息为:"+msg.obj.toString());
    }

    public MyHandler(Looper looper) {
        super(looper);
    }
}



另外还有:子线程给主线程发送数据 , 子线程给子线程发送数据; 其实对于Looper的理解也很简单,Handler的对象如果是以主线程构建的则处理主线程的MQ ,如果以子线程Looper对象创建Handler对象,则为处理子线程的MQ消息队列;
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics