线程中Handler收发消息机制实现

Looper实现机制:  全局静态(Looper.mThreadLocal)变量保存 多个: 线程-Looper键值对关系
// 全局变量:线程,Looper--->所有类都可以随时获得这里面的值,用于进程/类与类之间通信的全局变量
/*
实现机制:创建多个线程,每个线程都创建一个Looper(回圈),然后调用loop死循环查询当前进程的消息,
如果有消息就取出消息,回调消息内的函数(handleMessage)
问1:在每个线程调用loop绕回圈(死循环)的时候,如何获得当前线程的消息队列?
答1:每个线程的Looper(Looper里面有消息队列这个成员)和线程绑定在一起,每个线程在loop的时候都
通过当前线程这个key,找到当前线程对应的value(Loop)--->prepare的时候已经以键值对形式存入Looper
的全局变量中了

*/


     



// 函数调用关系--例子代码
new Thread(new Runnable(){
@Override
public void run() {
Handler lab3Handler  ;
Looper.prepare()  ; // 有点类似前期的初始化工作,做好布局(创建各种后面用到的对象,和这些对象之间的关系)
lab3Handler = new Handler(){


@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.i(CommonConstants.LOGCAT_TAG_NAME, "Get the message from "+msg.getData().getString(HANDLER_KEY)+" by Child Thread Handler")  ;
}
} ;

lab3Handler.sendMessage(defineNewMessage("Lab3")) ;
Looper.loop() ;
}
}).start() ;


1.prepare实现
public static void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper()); // 在一个线程中创建一个Looper
}


--> public void set(T value) {
        Thread currentThread = Thread.currentThread();
        Values values = values(currentThread);
        if (values == null) {
            values = initializeValues(currentThread);
        }
        values.put(this, value);
    }



2.loop实现机制
/**
 * Run the message queue in this thread. Be sure to call
 * {@link #quit()} to end the loop.
 */
public static void loop() {
Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
MessageQueue queue = me.mQueue;

// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();

while (true) {
Message msg = queue.next(); // might block
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}


long wallStart = 0;
long threadStart = 0;


// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
wallStart = SystemClock.currentTimeMicro();
threadStart = SystemClock.currentThreadTimeMicro();
}


msg.target.dispatchMessage(msg);


if (logging != null) {
long wallTime = SystemClock.currentTimeMicro() - wallStart;
long threadTime = SystemClock.currentThreadTimeMicro() - threadStart;


logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
if (logging instanceof Profiler) {
((Profiler) logging).profile(msg, wallStart, wallTime,
threadStart, threadTime);
}
}


// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}

msg.recycle();
}
}
}
-->
/**
     * Return the Looper object associated with the current thread.  Returns
     * null if the calling thread is not associated with a Looper.
     */
    public static Looper myLooper() {
        return sThreadLocal.get();
    }


3. new Handler()实现机制
    /**
     * Default constructor associates this handler with the queue for the
     * current thread.
     *
     * If there isn't one, this handler won't be able to receive messages.
     */
    public Handler() {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }


        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = null;
    }

--->
public static Looper myLooper() {
return sThreadLocal.get(); // 从步骤1中全局Looper.mThreadLocal获得和当前进程一致的Looper
// Looper中有信箱队列MessageQueue mQueue;
}

4.绕回圈实现机制
   public static void loop() {
        Looper me = myLooper(); // 返回当前线程对应的Looper,获得Looper就等于获取到消息队列了


        MessageQueue queue = me.mQueue; // 获取消息队列
        
        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();
        
        while (true) { // 死循环,防止线程退出
            Message msg = queue.next(); // might block // 获取当前线程队列中的数据
            if (msg != null) {
                if (msg.target == null) {
                    // No target is a magic identifier for the quit message.
                    return;
                }


                msg.target.dispatchMessage(msg); // target:Handler 内部调用handler的handleMessage
                
                msg.recycle();
            }
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值