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();
}
}
}
// 全局变量:线程,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();
}
}
}