美文网首页
自定义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