自定义Handler

2018-05-11  本文已影响63人  01_小小鱼_01

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

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;
    }
}
上一篇 下一篇

猜你喜欢

热点阅读