GpsLocationProvider中的消息处理机制
Daniel Wood 20110129
转载时请注明出处和作者
文章出处:http://danielwood.cublog.cn
作者:Daniel Wood
------------------------------------------------------------------------
GpsLocationProvider.java文件是连接framew层和JNI本地代码的纽带,其中有两个线程,分别为GpsEventThread和GpsLocationProviderThread。
GpsEventThread线程是用来处理底层事件触发的,GpsLocationProviderThread是用来处理上层对底层消息命令的。今天就分析这个线程,顺便讲讲Android的Looper消息处理机制。
GpsLocationProviderThread线程的启动是在GpsLocationProvider的构造函数里,代码如下:
mThread =
new
GpsLocationProviderThread(
)
;
mThread.
start
(
)
;
|
我们来看看它的run函数。
public
void
run
(
)
{
Process
.
setThreadPriority(
Process
.
THREAD_PRIORITY_BACKGROUND)
;
initialize
(
)
;
Looper.
prepare
(
)
;
mHandler =
new
ProviderHandler(
)
;
// signal when we are initialized and ready to go
mInitializedLatch.
countDown
(
)
;
Looper.
loop
(
)
;
}
|
run函数第一句指定了这个线程是后台运行的线程。
private
void
initialize
(
)
{
// register our receiver on our thread rather than the main thread
IntentFilter intentFilter =
new
IntentFilter(
)
;
intentFilter.
addAction(
ALARM_WAKEUP)
;
intentFilter.
addAction(
ALARM_TIMEOUT)
;
mContext.
registerReceiver(
mBroadcastReciever,
intentFilter)
;
}
|
initialize函数,只是注册了一个
BroadcastReciever
。
然后调用Looper.prepare();prepare()是Looper的static函数,所以可以直接通过类名来调用,基础知识狠重要。
public
static
final
void
prepare
(
)
{
if
(
sThreadLocal.
get
(
)
!
=
null
)
{
throw
new
RuntimeException
(
"Only one Looper may be created per thread"
)
;
}
sThreadLocal.
set
(
new
Looper(
)
)
;
}
|
在prepare()函数里面首先判断sThreadLocal.get是否为空,你没有set直接get当然为空。然后通过sThreadLocatl的set方法调用Looper的构造函数。
private
Looper(
)
{
mQueue =
new
MessageQueue(
)
;
mRun =
true;
mThread =
Thread
.
currentThread
(
)
;
}
|
每一个Looper都有一个属于自己的消息队列,就是MessageQueue,就是其内部成员变量mQueue。而且每个线程只能有一个Looper。然后通过
Thread
.
currentThread
(
)返回当前的线程
。
在Looper的prepare函数调用完了以后就新建一个Handle来分发和处理,消息队列中的消息。
mHandler =
new
ProviderHandler(
)
;
|
在哪个线程中,创建Handler,那个创建的Handler就和哪个线程的消息队列绑定了,不过在非主线程中创建Handler需要先调用Looper.prepaer()函数,上例就是这种情况。
我们来看一下ProviderHandler的构造函数,发现
ProviderHandler是继承自Handler,自己没有构造函数,当然调用父类
Handler的构造函数,并且是无参数构造函数。
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
;
}
|
FIND_POTENTIAL_LEAKS的值为false,所以前面的if语句块我们不管它。然后它调用Looper的myLooper函数。通过这个函数可以获得当前的Looper对象。
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public
static
final
Looper myLooper(
)
{
return
(
Looper)
sThreadLocal.
get
(
)
;
}
|
然后通过得到的Looper对象,将Handler中的消息队列赋值,Handler是用来处理消息的,当然会有一个消息队列。可见Handler和Looper两者的消息队列指的是同一个消息队列,当然和线程(GpsLocationProviderThread
)的消息队列也是同一个。
创建完Handler之后,调用 Looper.loop();函数,进入消息循环。
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public
static
final
void
loop
(
)
{
Looper me =
myLooper(
)
;
MessageQueue queue
=
me.
mQueue;
while
(
true)
{
Message msg =
queue
.
next
(
)
;
// might block
//if (!me.mRun) {
// break;
//}
if
(
msg !
=
null
)
{
if
(
msg.
target
=
=
null
)
{
// No target is a magic identifier for the quit message.
return
;
}
if
(
me.
null
)
me.
mLogging.
println
(
">>>>> Dispatching to "
+
msg.
target
+
" "
+
msg.
callback
+
": "
+
msg.
what
)
;
msg.
target
.
dispatchMessage(
msg)
;
if
(
me.
null
)
me.
mLogging.
println
(
"<<<<< Finished to "
+
msg.
target
+
" "
+
msg.
callback
)
;
msg.
recycle(
)
;
}
}
}
|
loop函数是个死循环,一直从消息队列mQueue中获取消息queue
.
next
(
)
,然后交给msg.
target进行消息的
处理,这里的msg.target当然是那个Handler(ProviderHandler
)。
我们来举个例子,看看具体是如何进程消息处理的。
上层LocationMangerService调用GPSLocationProvider的enable函数,(具体如何调用可以参考其他文章)
public
void
enable
(
)
{
synchronized
(
mHandler)
{
mHandler.
removeMessages(
ENABLE
)
;
Message m =
Message.
obtain(
mHandler,
ENABLE
)
;
m.
arg1 =
1;
mHandler.
sendMessage(
m)
;
}
}
|
首先从mHandler的消息移除ENABLE这个消息,这个不管。然后调用Message的static方法
obtain(
mHandler,
ENABLE
)。
public
static
Message obtain(
Handler
h,
int
what)
{
Message m =
obtain(
)
;
m.
target
=
h;
m.
what =
what;
return
m;
}
public
static
Message obtain(
)
{
synchronized
(
mPoolSync)
{
if
(
mPool !
=
null
)
{
Message m =
mPool;
mPool =
m.
next
;
m.
next
=
null
;
return
m;
}
}
return
new
Message(
)
;
}
|
通过Message的obtain方法可以创建一个Message,并且指定它的target为
mHandler。
然后通过
mHandler的
sendMessage方法将这个消息Message放入到消息队列中去。(代码略)
下面就是Looper.loop这个函数,不是一直从消息队列里面取消息然后分发给消息的target去处理吗?
msg.
target
.
dispatchMessage(
msg)
;
|
来看看mHandler的dispatchMessage函数,ProviderHandler当然没有也不需要实现了,它只实现了消息处理函数handleMessage,而
dispatchMessage函数最终调用的也是handleMessage函数去处理,ENABLE这个消息。
public
void
dispatchMessage(
Message msg)
{
if
(
msg.
callback
!
=
null
)
{
handleCallback(
msg)
;
}
else
{
if
(
mCallback !
=
null
)
{
if
(
mCallback.
handleMessage(
msg)
)
{
return
;
}
}
handleMessage(
msg)
;
}
}
|
处理函数为handleMessage中的第一个switch语句。
public
void
handleMessage(
Message msg)
{
switch
(
msg.
what)
{
case
ENABLE
:
if
(
msg.
arg1 =
=
1)
{
handleEnable(
)
;
}
else
{
handleDisable(
)
;
}
...
}
|
至此,从GpsLocationProvider的消息处理上面,我们就可以看到整个Android的消息处理过程。