深入浅出 - Android系统移植与平台开发(十三)- Android的对象管理

第六章、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一样。虽然这种方式创建的对象能够一直保存到手动释放,但是如果定义了大量堆对象,而忘记了释放,容易造成“内存泄漏”。另外,如果堆对象已经释放了,其它代码再通过指针访问这个对象时,就会造成系统崩溃。这时,我们希望有一个“智能管理者”,它能自动记录下一个对象被引用的次数,当一个对象的引用计数不为“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

};

轻量级指针类定义很简单,类中定义一个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\n", mRefs, this);

}

 

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

{

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

    if(mRefs->mWeak == 0) {

//       LOGV("Freeing refs %p of old RefBase %p\n", 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\n", 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\n", 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.\n");

        }

 

       virtual ~RefTest ()

        {

               printf("Destory RefTest Object. \n");

        }

};

 

int main(int argc, char** argv)

{

RefTest * pRefTest = new RefTest ();

       sp<RefTest>spRefTest = pRefTest;

 

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

 

        {

               sp<RefTest>spInner = pRefTest;

 

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

        }

 

        printf("Ref Count: %d.\n", 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编译成应用程序运行。

编译代码(RefTest工程放在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\n", 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手动删除实际对象。


mr_raptor CSDN认证博客专家 精益工程 驱动开发
北京同远天下创始人,专注于企业服务,企业系统解决方案,物联网,智慧社区,产品有众狐邮箱验证www.verify-mail.net,众狐微客服系统,著有《深入浅出嵌入式底层软件开发》北航出版社
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页