android 自定义looper,自定义Handler

在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对象而产生的垃圾回收问题。

494c21ceaf7a

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 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 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;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值