GpsLocationProvider中的消息处理机制

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值