手写一个简单的handler

handler主要是用来处理进程内通信的

首先我们先写一个handler

public class Handler {
    public void handleMessage( Message msg) {
    }
    public void sendMessage(Message msg){
    msg.setHandler(this);
    Looper.mq.enqueueMessage(msg);

    }
}

这两个是主要方法,一个发,一个收

public class Message {
    String msg ;
    Handler target ;
    Message next ;
    public  Message(String msg){
        this.msg = msg ;
    }
    public void setHandler(Handler handler){

        this.target  = handler ;
    }
    public Handler getHandler(){
        return this.target ;
    }

    @Override
    public String toString() {
        return "Message{" +
                "msg='" + msg + '\'' +
                '}';
    }
}

这是重写的简单的message

之后加入我们要发送和接收数据,当然如果我们只发送一个数据,我们就可直接使用handler的方法,当我们有大量数据时呢,如果都使用send,势必会导致线程阻塞,所以我们就想着添加一个队列,我们先把要发送的数据添加进去,之后他们想要处理的数据在慢慢处理,于是我们就写了

public class MessageQueue {
    Message mMessage =null;
public  void enqueueMessage(Message msg){
    Message p = mMessage;

    if (p == null ) {
        // New head, wake up the event queue if blocked.
        msg.next = p;
        mMessage = msg;

    } else {
        // Inserted within the middle of the queue.  Usually we don't have to wake
        // up the event queue unless there is a barrier at the head of the queue
        // and the message is the earliest asynchronous message in the queue.

        Message prev;
        for (;;) {
            prev = p;
            p = p.next;
            if (p == null) {
                break;
            }
        }
        msg.next = p; // invariant: p == prev.next
        prev.next = msg;
    }
    Log.d("xsr", "enqueueMessage: "+msg.toString());
    Log.d("xsr", "enqueueMessage: "+mMessage.toString());
}
public  Message next(){
    synchronized (this) {
       // Log.d("xsr", "next: "+mMessage.toString());
        if (mMessage == null) {
          return null ;
        }
        Message msg = mMessage; // 获取队列头的消息
        mMessage = msg.next; // 将队列头移动到下一个消息
        msg.next = null; // 断开与下一个消息的链接
        return msg; // 返回当前头消息
    }
}
}

消息添加到队列了,我们需要执行队列里方法的类,于是就有了looper

这里就需要思考一个问题了,looper可以有多个吗,我们看个方法就明白了

    public static void loop(){

        for(;;){
            final Looper me = sThreadLocal.get();
            Message msg  = me.mq.next();
            if(msg==null){
               break ;
            }
            msg.target.handleMessage(msg);
        }
    }

这是我简写的一个方法,他有个for循环会一直判断,如果有多个looper,前面的循环没执行完,后面就会一直阻塞,不就有发生之前的问题了吗,那queue将没有意义,所以我们要保证只有一个looper,那我们怎么做呢 我们想到threadLocal ,我们看下这个方法

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

他的key是当前线程, values我们可以存放一个looper,这样我们就可以得到这个唯一的looper了

我们看下方法实现

public class Looper {
    public static MessageQueue mq = new MessageQueue() ;
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    public static void prepare(){
        if(sThreadLocal.get()!=null){

        }
        sThreadLocal.set(new Looper());
    }
    public static void loop(){

        for(;;){
            final Looper me = sThreadLocal.get();
            Message msg  = me.mq.next();
            if(msg==null){
               break ;
            }
            msg.target.handleMessage(msg);
        }
    }
}

我们在prepare中确保了只有一个looper存在,然后使用loop执行

最后我们看下最终的调用

public class MainActivity extends Activity {
Handler mhand = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d("xsr", "onCreate: activity_main ");
        Looper.prepare();

new Thread(new Runnable() {
    @Override
    public void run() {

        Log.d("xsr", "thread ");
        mhand =  new Handler(){
            @Override
            public void handleMessage( Message msg) {
                Log.d("xsr", "handleMessage: "+msg.toString());
            }
        };
    }
}).start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        Log.d("xsr", "onCreate: send");
        mhand.sendMessage(new Message("xsr111"));
        mhand.sendMessage(new Message("xsr22"));
        mhand.sendMessage(new Message("xsr3"));
        Looper.loop();
    }
}

这样我们就实现了简易的handler通信

注意这里会存在内存泄露是因为长生命周期持有了短生命周期

threadlocal->queue->message->handler->activity

要解决内存泄漏简单方法是使用static静态方法来解决

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值