• 结合源代码详解android消息模型


    Handler是整个消息系统的核心,是Handler向MessageQueue发送的Message,最后Looper也是把消息通知给Handler,所以就从Handler讲起。

    一、Handler

    Handler的构造函数有很多,但本质差不多:

    public Handler() {  
            this(null, false);  
        }  
    

      

    public Handler(Callback callback, boolean async) {  
            //自动绑定当前线程的looper  
            mLooper = Looper.myLooper();  
            if (mLooper == null) {  
                throw new RuntimeException(  
                    "Can't create handler inside thread that has not called Looper.prepare()");//从这可以看出,创建Handler必须有Looper  
            }  
            mQueue = mLooper.mQueue;  //Looper的MessageQueue  
            mCallback = callback;     //一个回掉接口  
            mAsynchronous = async;    
        }  

    这个是创建给定Looper的Handler  :

    public Handler(Looper looper, Callback callback, boolean async) {    
           mLooper = looper;  
           mQueue = looper.mQueue;  
           mCallback = callback;  
           mAsynchronous = async;  
       }
    

    二、Looper的源代码:

    public static Looper myLooper() {  
           return sThreadLocal.get();  
       }  
    

      在一个子线程中创建Looper的一般步骤:(这是我自己写的,不是源代码)

    class MyThread extends Thread{  
            public Handler handler;  
            public Looper looper;  
            public void run() {  
                Looper.prepare();//创建一个looper  
                looper = Looper.myLooper();  
                handler = new Handler(){  
                   @Override  
                public void handleMessage(Message msg) {  
                      System.out.println("currentThread->"+Thread.currentThread());  
                   }  
               };  
               Looper.loop();//让消息循环起来  
            }  
        } 
    

      下面就看看Looper.prepare,Looper.loop方法:

    public static void prepare() {  
            prepare(true);  
        }  
      
        private static void prepare(boolean quitAllowed) {  
            if (sThreadLocal.get() != null) {//sThreadLocal使得线程能够保持各自独立的一个对象。  
                throw new RuntimeException("Only one Looper may be created per thread");  
            }  
            sThreadLocal.set(new Looper(quitAllowed));  
        }  
    

      Looper.prepare():

    public static void loop() {  
            final Looper me = myLooper();  
            if (me == null) {    //如果Looper为空  
                throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");  
            }  
            final MessageQueue queue = me.mQueue;  
      
            。。。。  
            for (;;) {  
                Message msg = queue.next(); // 循环下一个  
                if (msg == null) {  
                    // No message indicates that the message queue is quitting.  
                    return;  
                }  
      
               。。。。  
      
                msg.target.dispatchMessage(msg);  //分发消息,msg.target就是Handler  
      
                if (logging != null) {  
                    logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);  
                }  
                。。。。  
      
                msg.recycle();  //回收msg到msgPool  
            }  
        }  
    

      从这些代码可以看出Looper不断检查MessagePool是否有《==Message,有的话就通过Handler的dispatchMessage(msg)发送出去,利用Handler与外界交互。

    3.Message的源代码:

    public static Message obtain() {   //得到Message对象  
           synchronized (sPoolSync) {  
               if (sPool != null) {  
                   Message m = sPool;  
                   sPool = m.next;  
                   m.next = null;  
                   sPoolSize--;  
                   return m;  
               }  
           }  
           return new Message();  //没有就新建  
       } 
    

      handler.obtainMessage()方法:

    public final Message obtainMessage()  
       {  
           return Message.obtain(this);  //通过Message的obtain方法  
       }  
    

      

    public static Message obtain(Handler h) {  //就是这个方法  
          Message m = obtain();  //最终调用的还是obtain方法  
          m.target = h;      //target是handler  
      
          return m;  
      } 
    

      看了上边的源代码,相信你一定对Handler,message,Looper有了一定了解,对编程中常遇到的方法,知道是怎么用的啦。其实学android一定要常看源码,源码很有用。

    4.下边就是上代码,实例分析:

    <pre name="code" class="java">package com.example.handler_01;  
      
    import android.Manifest.permission;  
    import android.app.Activity;  
    import android.os.Bundle;  
    import android.os.Handler;  
    import android.os.Handler.Callback;  
    import android.os.Message;  
    import android.view.Menu;  
    import android.view.MenuItem;  
    import android.view.View;  
    import android.view.View.OnClickListener;  
    import android.widget.Button;  
    import android.widget.ImageView;  
    import android.widget.TextView;  
    import android.widget.Toast;  
      
    public class MainActivity extends Activity implements OnClickListener{  
      
        private TextView textView;  
        private Button button;  
          
          
        private Handler handler = new Handler(new Callback() {//拦截消息  
              
            public boolean handleMessage(Message msg) {  //截获handler的发送的消息  
              
                Toast.makeText(getApplicationContext(), ""+1, 1).show();  
                //return false;  
                return false;//若返回true,则证明截获,下面的handleMessage就不会执行!  
            }  
        }){  
            public void handleMessage(Message msg) {  
                Toast.makeText(getApplicationContext(), ""+2, 1).show();  
                Person person = (Person)msg.obj;  
                System.out.println(person.toString());  
            }  
        };  
          
        private MyRunnable myRunnable=new MyRunnable();  
          
        private ImageView imageView;  
          
        private int images[]={R.drawable.a1,R.drawable.a2,R.drawable.a3};  
        private int index;  
          
        class MyRunnable implements Runnable{  //不断的更新图片,3张轮换  
      
            @Override  
            public void run() {  
              index++;  
              index=index%3;  //不断循环  
              imageView.setImageResource(images[index]);  
              handler.postDelayed(myRunnable, 1000);  //每隔一段时间执行myRunnable  
              System.out.println("MyRunnable中的线程:"+Thread.currentThread());//运行在当前主线程!  
            }  
              
        }  
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
            textView = (TextView) findViewById(R.id.textview);  
            imageView = (ImageView) findViewById(R.id.imageView1);  
            button = (Button) findViewById(R.id.button1);  
            button.setOnClickListener(this);  
            new Thread(){  
                @Override  
                public void run() {  
                    try {  
                        Thread.sleep(2000);  
                        /*Message message = new Message(); 
                       message.arg1=88;*/  
                       Message message = handler.obtainMessage();  
                          
                       Person person = new Person();  
                       person.age=20;  
                       person.name="chaochao";  
                       message.obj=person;  
                       handler.sendMessage(message);//在子线程中向主线程发消息。  
                    } catch (InterruptedException e) {  
                        // TODO Auto-generated catch block  
                        e.printStackTrace();  
                    }  
                      
                }  
            }.start();  
            handler.postDelayed(myRunnable, 1000);  
        }  
        @Override  
        public void onClick(View v) {  
            switch (v.getId()) {  
            case R.id.button1:  
                handler.removeCallbacks(myRunnable);  
                //handler.sendEmptyMessage(1);  
                break;  
      
            default:  
                break;  
            }  
              
        }  
      
        class Person{  
            public int age;  
            public String name;  
              
            public String toString() {  
              return "name="+name+" age="+age;  
            }  
        }  
    }  
    

      布局很简单,就不上代码啦。

    运行结果:

    图片自己可以随便能一个。。。。

    在后边再详细解析Handler的用法。。

    转发请注明出处:http://www.cnblogs.com/jycboy/p/handlerjx.html

  • 相关阅读:
    server.c:5170:31: error: ‘struct redisServer'
    SpringBoot配置文件笔记:yaml语法,yaml如何写、注入配置文件类(2种方式根据业务场景选择)、多环境切换、配置文件加载优先级、指定位置加载配置文件
    微服务(Microservices)—— Martin Flower
    利用原生子窗体解决悬浮窗口播放的问题及踩坑记录
    uniapp中nvue页面如何使用iconfont字体图标
    项目经验踩坑记录:跨平台业务影响时注意要考虑多个平台
    SQL基础知识笔记:概述(层状/网状/关系模型)、数据类型、操作数据库能力(DDL/DML/DQL)、关系模型(主键、联合主键、外键、外键约束-性能影响、一对一、一对多、多对多、索引、索引效率)、实用SQL语句、事务(四个特性、四种隔离级别)
    Java的Maven基础知识笔记:Maven是什么、maven目录、pom.xml唯一ID、maven解决依赖管理、maven中央仓库与镜像、构建流程(声明周期、阶段、目标)、使用插件、模块管理、mvnw指定版本、如何发布自己的开源库
    Java里的IO基础知识笔记:IO流、字节流/字符流、File对象读取、输入流/输出流(使用过后及时关闭、缓冲区)、Filter模式、ZIP操作、读取classpath资源的意义、序列化/反序列化、Reader/Writer、使用Files工具类及其局限性
    推荐了解一个用于JavaScript的快速SQL数据库
  • 原文地址:https://www.cnblogs.com/jycboy/p/handlerjx.html
Copyright © 2020-2023  润新知