zoukankan      html  css  js  c++  java
  • 深入浅出

    第六章、Android的对象管理

    在Java中,不再使用的对象会通过gc机制来自己主动回收。而Android系统执行时库层代码是由C++编写的,在C++中创建的对象通常使用指针来操作,一旦使用不当。轻则造成内存泄漏,重则造成系统崩溃。

    只是在Android源代码实现中,它为我们提供了智能指针来对C++对象进行管理。这使得程序猿不再须要关注对象的生命周期、对象是否已经释放。

    本章主要内容例如以下:

    l 智能指针

    l RefBase类

    l 强指针

    l 弱指针

    5.1 智能指针

    在C++代码中创建对象有两种方式:创建栈对象和创建堆对象。

    创建栈对象:

    class A{

    public:

             A();

             ~A();

    private:

             intmVar1;

             intmVar2;

    };

    int main(int argc, char** argv){

    Aa();

    return0;

    }

    上述代码前面定义了一个类A。然后使用A a()来创建类A的对象a。这时a对象是在栈空间上分配的。我们能够通过“对象名.成员名”来訪问对象的成员。当退出了main函数作用域。a对象自己主动释放。

    栈对象的特点为:创建简单。使用后自己主动释放。

    可是有的场合我们希望创建的对象是个“全局对象”,即:对象保存下来直到合适的时间再被释放。这时我们就要创建一个堆对象。堆对象的创建例如以下:

    A *pa = new A();

    上述代码首先在栈上创建了A类的对象指针pa,然后在堆中为A对象分配空间,将对象地址赋值给pa。

    C++要求全部动态创建的堆对象都要手动通过delete来释放对象空间,如同C中的malloc和free一样。尽管这样的方式创建的对象能够一直保存到手动释放。可是假设定义了大量堆对象。而忘记了释放,easy造成“内存泄漏”。另外。假设堆对象已经释放了,其他代码再通过指针訪问这个对象时,就会造成系统崩溃。这时,我们希望有一个“智能管理者”,它能自己主动记录下一个对象被引用的次数,当一个对象的引用计数不为“0”。说明它还在被使用。假设引用计数为“0”,说明该对象没有人再去使用它,这时“自己主动”去释放掉该对象。这个“智能管理者”就是智能指针。

    智能指针(smartpointer)一种通用实现技术是使用引用计数(reference count)。智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类的 对象被引用次数。

    每次创建类的新对象时。初始化指针并将引用计数置为1;当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并添加与之相应的引用计数;对一个对象进行赋值时,赋值操作符“=”降低左操作数所指对象的引用计数(假设引用计数为减至0。则删除对象),并添加右操作数所指对象的引用计数。调用析构函数时,析构函数降低引用计数(假设引用计数减至0。则删除对象)。而且智能指针类中重载了operator->和operator*来返回原始对象指针,这样智能指针使用起来就像原始对象指针一起。

    Android中实现了两种智能指针:轻量级指针和强弱指针。

    5.2 轻量级指针

    Android智能指针的设计者为了隐藏智能指针的实现细节,通常将要隐藏的代码放到基类中,然后让子类去继承该基类,通过复用代码,降低编程人员工作量和程序设计的复杂程序。在轻量级指针设计时,设计者将智能指针引用计数操作接口封装到了LightRefBase这个基类中。当我们使用智能指针时,仅仅要继承LightRefBase类,那么子类对象就具有智能管理功能了。LightRefBase类定义例如以下:

     @frameworks/base/include/utils/RefBase.h

    template <class T>

    class LightRefBase

    {

    public:

             inlineLightRefBase() : mCount(0) { }          //初始化引用计数值为0

             inlinevoid incStrong(const void* id) const {                   //添加引用计数

                       android_atomic_inc(&mCount);

             }

             inlinevoid decStrong(const void* id) const {                  //降低引用计数

                       if(android_atomic_dec(&mCount) == 1) {

                                deletestatic_cast<const T*>(this);

                       }

             }

             //!DEBUGGING ONLY: Get current strong ref count.

             inlineint32_t getStrongCount() const {                //返回当前引用计数值

                       returnmCount;

             }

    protected:

             inline~LightRefBase() { }

    private:

             mutablevolatile int32_t mCount;                         //定义引用计数变量mCount

    };

    轻量级指针类定义非常easy。类中定义一个mCount变量,它的初始化值为0,另外,这个类还提供两个成员函数incStrong和decStrong来维护引用计数器的值。这两个函数就是提供给智能指针来调用的。这里要注意的是,在decStrong函数中,假设当前引用计数值为1。那么当减1后就会变成0,于是就会delete这个对象。

     

             上述类仅仅是定义了引用计数变量和引用计数的两个操作函数,真正对引用计数进行管理的是智能指针类sp。

    @frameworks/base/include/utils/RefBase.h

    template <typename T>

    class sp

    {

    public:

       typedef typename RefBase::weakref_typeweakref_type;

        inlinesp() : m_ptr(0) { }

        sp(T*other);

       sp(const sp<T>& other);

       template<typename U> sp(U* other);

       template<typename U> sp(const sp<U>& other);

        ~sp();

        //Assignment 

       sp& operator = (T* other);

       sp& operator = (const sp<T>& other);

       template<typename U> sp& operator = (const sp<U>&oth22er);

       template<typename U> sp& operator = (U* other);

        //Reset      

        voidclear();

        //Accessors 

       inline  T&     operator* () const  { return *m_ptr; }

       inline  T*      operator-> () const { returnm_ptr;  }      // 对“->”运算符进行重载

       inline  T*      get() const         { return m_ptr; }

    private:

       template<typename Y> friend class sp;

       template<typename Y> friend class wp;

        //Optimization for wp::promote().

        sp(T*p, weakref_type* refs); 

        T*              m_ptr;

    };

    template<typename T>

    sp<T>::sp(T* other)                                   // 构造函数參数为T类型指针

        :m_ptr(other)

    {

        if(other) other->incStrong(this);                    //当创建sp对象时,添加强引用计数

    }

    template<typename T>

    sp<T>::sp(const sp<T>& other)                          // 构造函数參数为T类型引用对象

        :m_ptr(other.m_ptr)

    {

        if(m_ptr) m_ptr->incStrong(this);

    }

    template<typename T>

    sp<T>::~sp()

    {

        if(m_ptr) m_ptr->decStrong(this);                  //当析构sp对象时。降低强引用计数

    }

    template<typename T>

     sp<T>& sp<T>::operator = (T*other)                 // 对“=”运算符进行重载

     {

         if(other) other->incStrong(this);                   //添加other对象强引用计数

         if(m_ptr) m_ptr->decStrong(this);                //降低sp对象持有的旧对象强引用计数

         m_ptr= other;                                   //将other对象保存到sp对象中

        return *this;

     }

    由sp类的定义可知。sp被定义为模板类。它拥有一个T指针类型的属性m_ptr,当创建sp对象时。将T类型指针或T类型引用赋值给m_ptr,同一时候调用m_ptr的incStrong方法来添加引用计数,由此可见。m_ptr的T类型应该是LightRefBase的子类。它就是我们要进行管理的目标对象。当sp对象生命周期结束时。会调用它的析构函数~sp,析构函数中调用m_ptr的decStrong的来降低强引用计数,当引用计数减为0时将目标对象delete。

    sp类对“->”运算符进行了重载,当sp对象使用运算符“->”时。返回m_ptr指针。这样相当于“T->成员”訪问。通过运算符重载将sp对象操作转化成了T对象操作,保证了LightRefBase子类能訪问到自己的成员。

    sp类还对“=”运算符进行了重载,将一个T指针类型other作为“=”右值时,首先会添加other对象的强引用计数。降低sp之前引用对象的强引用计数。然后再将other对象保存在m_ptr中,从而让sp对象指向新的对象other。

     

    我们能够总结出,在Android轻量级智能指针实现中有下面规定:

    l LightRefBase类(或其子类)的对象能够通过智能指针sp进行管理

    l 当使用智能指针sp指向、赋值、初始化LightRefBase对象时,该对象引用计数加1。

    l 当sp指针使用完后,其指向的对象引用计数自己主动减1。

    l 当LightRefBase对象的引用计数为0时,该对象会被delete。

    通过对Android轻量级指针类LightRefBase和智能指针类sp代码分析可知。Android中定义的这套智能指针,能够简单有效的对Android本地对象进行管理。提高代码的编写效率。在Android系统中。除了轻量级智能指针外,还有支持强指针(Strong Pointer)和弱指针(WeakPointer)的RefBase重量级指针类。

    5.3 RefBase

             RefBase类的定义还是比較复杂的。它里面并没有我们预想中的计数变量的直接定义。而是将计数放在了一个叫weak_impl的类中进行封装。

             RefBase类中不仅仅定义了mStrong强引用计数。而且另一个mWeak的弱引用计数,强引用计数主要被sp对象管理。弱引用计数主要被wp对象管理。

    RefBase的定义简化代码例如以下:

    @frameworks/base/include/utils/RefBase.h

    class RefBase

    {

    public

               void            incStrong(constvoid* id) const;

               void            decStrong(constvoid* id) const;

         classweakref_type

         {

        public:

            RefBase*       refBase() const;

            void                incWeak(constvoid* id);

            void                decWeak(constvoid* id);

         };

     protected:

                                 RefBase();

        virtual              ~RefBase();

         enum{

            OBJECT_LIFETIME_WEAK    = 0x0001,             // 目标对象受弱引用计数影响标志

            OBJECT_LIFETIME_FOREVER = 0x0003              //目标对象不受强、弱引用计数影响标志

         };

        virtual void       onFirstRef();

        virtual void      onLastStrongRef(const void* id);

        virtual void      onLastWeakRef(const void* id); 

    private:

        friend class weakref_type;

         classweakref_impl;

        weakref_impl* const mRefs; 

     };

    RefBase::RefBase()                                   // 构造函数,创建weakref_impl对象赋值给mRefs

        :mRefs(new weakref_impl(this))

    {

    //   LOGV("Creating refs %p with RefBase %p ", mRefs, this);

    }

    RefBase::~RefBase()                                 // 析构函数,当弱引用计数减为0时,删除mRefs指向的对象

    {

    //   LOGV("Destroying RefBase %p (refs %p) ", this, mRefs);

        if(mRefs->mWeak == 0) {

    //       LOGV("Freeing refs %p of old RefBase %p ", mRefs, this);

           delete mRefs;

        }

    }

    void RefBase::incStrong(const void* id) const     // 添加强引用计数

    {

       weakref_impl* const refs = mRefs;

       refs->addWeakRef(id);

       refs->incWeak(id);                               //先添加弱引用计数

       refs->addStrongRef(id);                       //再添加弱引用计数

        constint32_t c = android_atomic_inc(&refs->mStrong);

       LOG_ASSERT(c > 0, "incStrong() called on %p after last strongref", refs);

    #if PRINT_REFS

       LOGD("incStrong of %p from %p: cnt=%d ", this, id, c);

    #endif

        if (c!= INITIAL_STRONG_VALUE)  {

           return;

        }

       android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);

       const_cast<RefBase*>(this)->onFirstRef();    // 当第一次强引用时调用onFirstRef接口

    }

    void RefBase::decStrong(const void* id) const

    {

       weakref_impl* const refs = mRefs;

       refs->removeStrongRef(id);

        constint32_t c = android_atomic_dec(&refs->mStrong);  // 降低强引用计数

    #if PRINT_REFS

       LOGD("decStrong of %p from %p: cnt=%d ", this, id, c);

    #endif

       LOG_ASSERT(c >= 1, "decStrong() called on %p too manytimes", refs);

        if (c== 1) {

           const_cast<RefBase*>(this)->onLastStrongRef(id);  // 当最后一次强引用对象时回调onLastStrongRef

            if((refs->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {

               delete this;                                      //当目标对象生命周期不受弱引用计数影响时,删除目标对象

            }

        }

       refs->removeWeakRef(id);

       refs->decWeak(id);

    }

    当中。在构造RefBase类时。创建了一个weakref_impl对象,它用来封装强、弱引用计数变量和目标对象影响标记。它是weakref_type的子类。

    class RefBase::weakref_impl : public RefBase::weakref_type

    {

    public:

       volatile int32_t    mStrong;                // 强引用计数变量

       volatile int32_t    mWeak;                 // 弱引用计数变量

       RefBase* const      mBase;

    volatileint32_t    mFlags;            // 目标对象是否受引用计数标志变量

       Destroyer*          mDestroyer;

    #if !DEBUG_REFS

       weakref_impl(RefBase* base)

            :mStrong(INITIAL_STRONG_VALUE)

            ,mWeak(0)

            ,mBase(base)

            , mFlags(0)      //初始化为0,即不是OBJECT_LIFETIME_WEAK。也不是OBJECT_LIFETIME_FOREVER

            ,mDestroyer(0)

        {

        }

    虚函数onFirstRef、onLastStrongRef、onLastWeakRef能够在子类中实现,当RefBase的子类对象被第一次强引用、最后一次强引用、最后一次弱引用时被回调,onFirstRef函数主要用来在Android对象创建时做一些初始化操作,onLastStrongRef用来在Android对象销毁前做一些“收尾“工作。

     

    RefBase里incStrong和decStrong用来添加强引用计数。incStrong添加强引用计数同一时候添加弱引用计数,在decStrong中,降低强引用计数,假设在强引用计数变为0。而且目标对象标记为非OBJECT_LIFETIME_WEAK(目标对象生命周期不受弱引用计数影响),删除目标对象。

    依据面向对象继承原理,仅仅要我们的类继承RefBase类,那么这个子类就拥有更强的“自己主动管理对象能力”。同一时候它还能够让子类对象通过覆盖onXXXRef方法实如今对象创建时和销毁时完毕特定功能的能力。

     

    尽管RefBase类提供了强弱引用计数和相应的操作接口,为了实现智能管理对象,通常我们一般不须要手动调用强弱引用操作接口,真正对计数进行操作的是强指针引用对象 sp和弱引用计数wp对象。

    l sp强指针对象:

    sp对象能够通过“->”执行符直接訪问目标对象成员,而且直接管理着目标对象的销毁

    l wp弱指针对象:

    wp表示对一个目标对象的弱引用。它不能直接訪问目标对象成员,仅仅表示两者间存在引用关系。假设wp想訪问目标对象。则必须由弱引用升级成强引用。

    使用sp和wp有下面规定:

    l RefBase对象中有一个隐含的对象mRefs,该对象内部有强弱引用计数

    l RefBase类(或其子类)的对象能够通过sp和wp对象进行管理

    l 当目标对象被sp引用时。表示对目标对象强引用。其强、弱引用计数各加1。

    l 当目标对象被wp引用时,表示对目标对象弱引用。其弱引用计数加1。

    l 目标对象的生死由weakref_impl.mFlags和引用类型决定:

    n 当目标对象weakref_impl.mFlags标记为OBJECT_LIFETIME_FOREVER时,对象不受强、弱引用计数影响。

    n 当目标对象的强、弱引用计数为0且标记为OBJECT_LIFETIME_WEAK时,目标对象会被删除。

    n 当目标对象的强引用计数为0而且标记为默认值0(非OBJECT_LIFETIME_WEAK和OBJECT_LIFETIME_FOREVER)时。该目标对象被delete。

    在5.2节我们已经分析过sp的实现代码,它通过运算符重载、拷贝构造函数、构造函数、析构函数机制实现了目标对象指针的赋值、引用等操作。

    我们来看使用sp的样例:

    我们先创建RefBase的子类RefTest.cpp:

    #include <stdio.h>

    #include <utils/RefBase.h>

    using namespace android;

    class RefTest: public RefBase

    {

    public:

    RefTest ()

            {

                   printf("Construct RefTest Object. ");

            }

           virtual ~RefTest ()

            {

                   printf("Destory RefTest Object. ");

            }

    };

    int main(int argc, char** argv)

    {

    RefTest * pRefTest = new RefTest ();

           sp<RefTest>spRefTest = pRefTest;

           printf("Ref Count: %d. ", pRefTest->getStrongCount());

            {

                   sp<RefTest>spInner = pRefTest;

                   printf("Ref Count: %d. ", RefTest->getStrongCount());

            }

            printf("Ref Count: %d. ", RefTest->getStrongCount());

           return 0;

    }

    我们首先定义了一个类RefTest它继承了RefBase,在RefTest中的构造函数和析构函数中仅打印一句话。在main函数中首先创建一个RefTest类的堆对象pRefTest,然后声明强引用对象spRefTest,模板类型为RefTest。

    依据RefBase中对“=”执行符重载可知,将pRefTest赋值给spRefTest时,会添加pRefTest强引用计数,打印出当前强引用计数。然后在“{}”内再次将RefTest对象赋值给强引用对象spInner。打印出强引用计数,“{}”内代码执行完毕,spInner对象销毁,这时在~sp析构函数内自己主动将对RefTest对象强引用计数减1。

    再次打印强引用计数值。

    要想查看上述代码的执行结果。依据第四章内容可知。我们必须要编写一个Android.mk文件:

    LOCAL_PATH:= $(call my-dir)

    include $(CLEAR_VARS)

    LOCAL_SRC_FILES:=

            RefTest.cpp

    LOCAL_SHARED_LIBRARIES :=

           libcutils

           libutils

    LOCAL_MODULE:= RefTest

    include $(BUILD_EXECUTABLE)

    在Android.mk中指定用到的两个库:libcutils(Android中的C库)和libutils(RefBase所在的库),然后将RefTest.cpp编译成应用程序执行。

    编译代码(RefTestproject放在xxx文件夹下):

    $ mmm device/farsight/chapter5/RefTest

    生成新的Android映像:

    $ make snod

    执行结果例如以下:

    # RefTest

    Construct RefTest Object.

    Ref Count: 1.

    Ref Count: 2.

    Ref Count: 1.

    Destory RefTest Object.

    由执行结果可清楚看到,强引用计数随着sp所持有次数在改变,我们总结例如以下:

    l 要想对Android本地对象进行智能管理。该对象必须是RefBase的子类对象

    l 本地对象必须结合sp对象来联合使用,sp实现了对强引用计数的自己主动管理

    因为强引用计数决定了本地对象的生死。所以sp用来持有必须依赖的对象

    5.2 弱引用指针wp

    弱引用指针wp表示对一个目标对象的弱引用关系。它不能和sp一样直接訪问目标对象成员,假设wp想訪问目标对象。则必须由弱引用升级成强引用。

    弱引用wp的实现代码:

    @frameworks/base/include/utils/RefBase.h

    template <typename T>

    class wp

    {

    public:

       typedef typename RefBase::weakref_type weakref_type;

        inlinewp() : m_ptr(0) { }

        wp(T*other);

       wp(const wp<T>& other);

       wp(const sp<T>& other);

       template<typename U> wp(U* other);

       template<typename U> wp(const sp<U>& other);

       template<typename U> wp(const wp<U>& other);

        ~wp();

        //Assignment

       wp& operator = (T* other);

       wp& operator = (const wp<T>& other);

       wp& operator = (const sp<T>& other);

       template<typename U> wp& operator = (U* other);

       template<typename U> wp& operator = (const wp<U>&other);

       template<typename U> wp& operator = (const sp<U>&other);

    voidset_object_and_refs(T* other, weakref_type* refs);

        //promotion to sp

    sp<T>promote() const;

    voidclear();

    private:

       template<typename Y> friend class sp;

       template<typename Y> friend class wp;

        T*              m_ptr;

    weakref_type*   m_refs;

    };

    通过代码可知,在wp中持有T类型指针m_ptr和weakref_type类型指针m_refs。通过构造函数能够看出,它能够接收wp和sp引用或指针来构造新wp对象,在wp中定义一个promote函数,它用来将一个弱引用升级为强引用。wp也重载了“=”运算符,可是没有实现运算符“->”、“*”,说明我们能够为wp赋值。而不能通过wp直接訪问目标对象。wp还实现了clear方法。该方法用来清除弱引用指针,降低对实际对象的弱引用计数。将m_ptr指针清空。

    template<typename T>

    wp<T>::wp(const wp<T>& other)                // 拷贝构造函数,接收弱引用

        :m_ptr(other.m_ptr), m_refs(other.m_refs)

    {

        if(m_ptr) m_refs->incWeak(this);

    }

    template<typename T>

    wp<T>::~wp()

    {

        if(m_ptr) m_refs->decWeak(this);

    }

    template<typename T>

    wp<T>& wp<T>::operator = (constsp<T>& other)         // “=”执行符重载

    {

       weakref_type* newRefs =

           other != NULL ? other->createWeak(this) : 0;

        if(m_ptr) m_refs->decWeak(this);

        m_ptr= other.get();

        m_refs= newRefs;

        return*this;

    }

    template<typename T>

    voidsp<T>::clear()

    {

        if(m_ptr) {

           m_ptr->decWeak(this);

           m_ptr = 0;

        }

    }

    当wp对象创建或赋值时,都会添加弱引用计数,当wp析构时。调用decWeak函数降低引用计数。当弱引用计数等于1时,要依据impl->mFlags标记来决定,当mFlags为OBJECT_LIFETIME_WEAK时,表示目标对象生命周期受弱引用计数影响。回调onLastWeakRef方法,而且delete目标对象,当mFlags为OBJECT_LIFETIME_FOREVER。说明目标对象生命周期不受引用计数影响,目标对象永远不能被删除。

    @frameworks/base/libs/utils/RefBase.cpp

    void RefBase::weakref_type::incWeak(const void*id)                      

    {

       weakref_impl* const impl = static_cast<weakref_impl*>(this);

       impl->addWeakRef(id);

        constint32_t c = android_atomic_inc(&impl->mWeak);    // Android自己实现的原子添加计数

       LOG_ASSERT(c >= 0, "incWeak called on %p after last weakref", this);

    }

    void RefBase::weakref_type::decWeak(const void*id)

    {

       weakref_impl* const impl = static_cast<weakref_impl*>(this);

       impl->removeWeakRef(id);

        constint32_t c = android_atomic_dec(&impl->mWeak);   // 降低弱引用计数

       LOG_ASSERT(c >= 1, "decWeak called on %p too many times",this);

        if (c!= 1) return;                                            //当弱引用计数 !=1 时,直接返回

        if((impl->mFlags&OBJECT_LIFETIME_WEAK) != OBJECT_LIFETIME_WEAK) {

            if(impl->mStrong == INITIAL_STRONG_VALUE)                //标记为INITIAL_STRONG_VALUE

               delete impl->mBase;                                 // 释放RefBase对象

           else {

    //           LOGV("Freeing refs %p of old RefBase %p ", this,impl->mBase);

               delete impl;                                              //释放内置的weakref_type对象

            }

        } else{                                                //标记为OBJECT_LIFETIME_WEAK

           impl->mBase->onLastWeakRef(id);                          

            if((impl->mFlags&OBJECT_LIFETIME_FOREVER) != OBJECT_LIFETIME_FOREVER) {

               delete impl->mBase;                                 //标记为非OBJECT_LIFETIME_FOREVER时

                                                            //仅仅释放RefBase对象

            }

        }

    }

    5.3 智能指针的演示样例

    在Android系统中硬件资源通常被共享使用,如摄像头、传感器、Wifi等。

    这些硬件资源通常被封装成Service用于向其他使用者提供硬件服务,这些使用者被称为Client。

    在Android应用程序中可能同一时候多个应用程序使用同一硬件资源。即:可能存在多个Client要訪问Service。

    在Service中维护这些Client对象往往使用智能指针来控制。我们以摄像头为例来说明。

    摄像头的Service为CameraService封装类,其定义例如以下:

    @frameworks/base/services/camera/libcameraservice/CameraService.h

    class CameraService :publicBinderService<CameraService>,public BnCameraService

     {

             ……

    private:

    wp<Client>          mClient[MAX_CAMERAS];

             ……

    classClient : public BnCamera

             {……}

    }

    在CameraService中定义了一个对象数组mClient,其成员为Client对象的wp弱引用类型指针。即:该对象并不决定实际对象的生死(mFlags为默认值)。

    它主要用于服务端保持对连接客户端对象地址,当Android应用程序訪问CameraService时,调用Connect方法来保持和Service的连接进行通信。

    @frameworks/base/services/camera/libcameraservice/CameraService.cpp

    sp<ICamera> CameraService::connect(constsp<ICameraClient>& cameraClient, int cameraId) {

             …

    sp<Client>client;

    if(mClient[cameraId] != 0) {

    client = mClient[cameraId].promote();

             …

             returnNULL;

                     }

    client= new Client(this, cameraClient, hardware, cameraId, info.facing,callingPid);

    mClient[cameraId]= client;

             returnclient;

    }

    在Connect方法内首先推断client对象是否存在,假设存在说明该Client正在和Service进行通信。返回NULL。假设client对象不存在,创建了Client对象。使用sp保持对该对象的强引用,同一时候将Client对象的wp弱引用保存在mClient数组中,sp强引用client在当前方法使用完后被析构,其对象被智能指针管理。

    当我们想使用某个Client对象时,仅仅须要提供其cameraID就可以,假设该Client对象已经被智能指针释放,可是因为wp指针数组mClient还维持着弱引用,能够调用弱引用的promote来进行“由弱升强”将对象又一次创建并使用。

    sp<CameraService::Client>CameraService::getClientById(int cameraId) {

    if(cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;

    returnmClient[cameraId].promote();

    }

    当Android应用程序不在使用CameraService时,调用removeClient来释放指定的连接。

    void CameraService::removeClient(constsp<ICameraClient>& cameraClient) {

    for(int i = 0; i < mNumberOfCameras; i++) {         // 循环遍历全部的客户端连接对象

                       sp<Client>client;   

                       if(mClient[i] == 0) continue;

                       client= mClient[i].promote();             // 由弱转强

       if (client == 0) {                              //假设强引用对象为空

                                mClient[i].clear();            // 删除对Client对象的弱引用

                                continue;

                       }

                       if(cameraClient->asBinder() == client->getCameraClient()->asBinder()) {  // 假设是指定的待释放连接

                                mClient[i].clear();                   //删除对Client对象的弱引用

                                break;

                       }

             }

    }

    智能指针使用要点:

    l Android中智能指针分为:轻量级LightRefBase和重量级RefBase。LightRefBase仅仅能使用sp指针,主要用于简单的管理一些全局对象的自己主动释放。通经常使用于简单逻辑处理,而RefBase相对来说功能更强大,不仅仅通过sp指针决定对象生命周期。还能够通过wp指针来维持对象的引用关系,通过“由弱升强”来訪问对象成员。而且RefBase能够通过设置mFlags来限制智能指针对实际对象生命周期的影响。

    l 智能指针能够管理的对象必须是LightRefBase或RefBase的子类对象。

    l 当使用智能指针管理对象时,不要试图通过delete手动删除实际对象。


  • 相关阅读:
    机器学习(01)——机器学习简介
    Harbor本地镜像库安装与使用
    大数据高可用集群环境安装与配置(10)——安装Kafka高可用集群
    大数据高可用集群环境安装与配置(09)——安装Spark高可用集群
    大数据高可用集群环境安装与配置(08)——安装Ganglia监控集群
    大数据高可用集群环境安装与配置(07)——安装HBase高可用集群
    大数据高可用集群环境安装与配置(06)——安装Hadoop高可用集群
    大数据高可用集群环境安装与配置(05)——安装zookeeper集群
    大数据高可用集群环境安装与配置(04)——安装JAVA运行环境
    大数据高可用集群环境安装与配置(03)——设置SSH免密登录
  • 原文地址:https://www.cnblogs.com/brucemengbm/p/6710200.html
Copyright © 2011-2022 走看看