美文网首页
自定义Handler

自定义Handler

作者: 01_小小鱼_01 | 来源:发表于2018-05-11 23:10 被阅读63次

    在Android 消息机制里面主要如下几个类Looper、MessageQueue、Message、Handler,下面简单的介绍一下他们之间的关系。

    • Looper
      每一个线程只有一个Looper,每个线程在初始化Looper之后,然后Looper会维护好该线程的消息队列,用来存放Handler发送的Message,并处理消息队列出队的Message。它的特点是它跟它的线程是绑定的,处理消息也是在Looper所在的线程去处理,所以当我们在主线程创建Handler时,它就会跟主线程唯一的Looper绑定,从而我们使用Handler在子线程发消息时,最终也是在主线程处理,达到了异步的效果。

    • MessageQueue
      MessageQueue是一个消息队列,用来存放Handler发送的消息。每个线程最多只有一个MessageQueue。MessageQueue通常都是由Looper来管理,而主线程创建时,会创建一个默认的Looper对象,而Looper对象的创建,将自动创建一个MessageQueue。其他非主线程,不会自动创建Looper。

    • Message
      消息对象,就是MessageQueue里面存放的对象,一个MessageQueu可以包括多个Message。当我们需要发送一个Message时,我们一般不建议使用new Message()的形式来创建,更推荐使用Message.obtain()来获取Message实例,因为在Message类里面定义了一个消息池,当消息池里存在未使用的消息时,便返回,如果没有未使用的消息,则通过new的方式创建返回,所以使用Message.obtain()的方式来获取实例可以大大减少当有大量Message对象而产生的垃圾回收问题。

    h (1).png

    1. 自定义消息实体Message.java

    public class Message {
        public int msg1;
        public int msg2;
        public int what;
        public Object obj;
        public Handler target;
        public Runnable runnable;
    }
    

    2. 自定义消息队列-MessageQueue.java

    public class MessageQueue {
    
        private BlockingQueue<Message> queue;
        private boolean quit = false;
    
        public MessageQueue() {
            queue = new LinkedBlockingQueue<>();
            queue.clear();
        }
    
        //入队
        public boolean enqueueMessage(Message msg) {
            if (msg.target == null) {
                throw new RuntimeException("消息必须有一个消息处理者");
            }
            try {
                queue.put(msg);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return true;
        }
    
        //出队
        public Message next() {
            Message msg = null;
            if (quit) {
                return null;
            }
            try {
                msg = queue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return msg;
        }
    
        //销毁
        public synchronized void quit() {
            quit = true;
        }
    }
    

    3. 自定义消息循环器-Looper.java

    public class Looper {
    
        private static ThreadLocal<Looper> threadLocal = new ThreadLocal<>();
        private static Looper mLooper;
        public MessageQueue queue;
        //一个线程对应一个阻塞队列
    
        private Looper() {
            queue = new MessageQueue();
        }
    
        //获取当前线程相对应的Looper对象
        public static Looper myLooper() {
            return threadLocal.get();
            //当未调用prepare()方法时。ThreadLocal.get()方法返回的为null;
        }
    
        //为本线程准备对应的MyLooper对象
        public static void prepare() {
            if (threadLocal.get() != null) {
                throw new RuntimeException( "Only one MyLooper may be created
                per thread");
            }
            threadLocal.set(new Looper());
        }
    
        //这里启动消息循环
        public static void loop() {
            while (true) {
                mLooper = Looper();
                MessageQueue mQueue = mLooper.queue;
                Message msg = mQueue.next();
                // take()方法是个阻塞方法。线程运行到此会阻塞住。以准备接收发过来的消息
                msg.target.dispatchMessage(msg);
            }
        }
    }
    

    4. 自定义消息处理器-Handler.java

    public class Handler {
    
        private MessageQueue queue;// 用于进行线程间通信的阻塞队列
        private CallBack callBack; // 处理消息的回调
    
        public Handler(CallBack callBack) {
            Looper looper = Looper.myLooper();
            if (looper == null) {
                throw new RuntimeException("在新开的线程中。创建MyHandler对象
                                           需要先调用Looper.prepare()方法。");
            }
            queue = looper.queue;
            this.callBack = callBack;
        }
    
        //消息接收的回调
        public interface CallBack {
            void handleMessage(Message msg);
        }
    
        //发送消息
        public void sendMessage(Message msg) {
            msg.target = this;
            queue.enqueueMessage(msg);
        }
    
        //派发消息
        public void dispatchMessage(Message msg) {
            callBack.handleMessage(msg);
        }
    }
    

    5. 测试代码TestClient.java

    public class TestClient {
    
        Handler mainHandler;
    
        public static void main(String[] args) {
            new TestClient().test();
        }
    
        private void test() {
            //初始化主线程Looper
            Looper.prepare();
            mainHandler = new Handler(new CallBack() {
                @Override
                public void handleMessage(Message msg) {
                    // 刷新界面
                    String obj = (String) msg.obj;
                    LogUtil.print("刷新界面:" + obj);
                }
            });
            //发起网络请求
            LogUtil.print("在主线程发起一个网络请求");
            NetThread netThread = new NetThread("http://baidu.com");
            netThread.start();
            LogUtil.print("在主线程继续其它操作");
    
            //开始消息循环
            Looper.loop();
        }
    
    
        //网络线程类
        private class NetThread extends Thread {
            private String url;
    
            public NetThread(String url) {
                this.url = url;
            }
    
            @Override
            public void run() {
                String body = getWebData(url);
                senior.thread_concurrent.handler.MyMessage msg = new senior.thread_concurrent.handler.MyMessage();
                msg.obj = body;
                mainHandler.sendMessage(msg);
            }
        }
    
        //执行网络请求
        private String getWebData(String url) {
            LogUtil.print("执行请求网络:" + url);
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            String body = "这是" + url + "的响应值";
            LogUtil.print("请求网络成功:" + body);
            return body;
        }
    }
    

    相关文章

      网友评论

          本文标题:自定义Handler

          本文链接:https://www.haomeiwen.com/subject/nnbqdftx.html