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的消息处理过程。