第六章、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这个对象。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbXJfcmFwdG9y/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />

上述类仅仅是定义了引用计数变量和引用计数的两个操作函数,真正对引用计数进行管理的是智能指针类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编译成应用程序执行。

编译代码(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\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手动删除实际对象。

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

  1. 深入浅出 - Android系统移植与平台开发(一)

    深入浅出 - Android系统移植与平台开发(一) 分类: Android移植2012-09-05 14:16 16173人阅读 评论(12) 收藏 举报 androidgitgooglejdkub ...

  2. 深入浅出 - Android系统移植与平台开发(五)- 编译Android源码(转)

    2.3编译Android源码 Android源码体积非常庞大,由Dalvik虚拟机.Linux内核.编译系统.框架代码.Android定制C库.测试套件.系统应用程序等部分组成,在编译Android源 ...

  3. 深入浅出-Android系统移植与平台开发(一)- Android4.0系统的下载与编译

    作者:唐老师,华清远见嵌入式学院讲师. 一.Android4.0系统的下载与编译 Android系统的下载与编译,Google的官方网站上已经给出了详细的说明,请参照Android的官方网址: htt ...

  4. 深入浅出 - Android系统移植与平台开发(三)- 编译并运行Android4.0模拟器

    作者:唐老师,华清远见嵌入式学院讲师. 1.   编译Android模拟器 在Ubuntu下,我们可以在源码里编译出自己的模拟器及SDK等编译工具,当然这个和在windows里下载的看起来没有什么区别 ...

  5. 深入浅出 - Android系统移植与平台开发(十)- Android编译系统与定制Android平台系统(瘋耔修改篇二)

    第四章.Android编译系统与定制Android平台系统 4.1Android编译系统 Android的源码由几十万个文件构成,这些文件之间有的相互依赖,有的又相互独立,它们按功能或类型又被放到不同 ...

  6. 深入浅出 - Android系统移植与平台开发(十一)- Android系统的定制(瘋耔修改篇一)

    首先非常感谢原文作者为我们提供的知识库,因为有你们的贡献,我们的开发难度更显简单 原文 :   http://blog.csdn.net/mr_raptor/article/details/30113 ...

  7. 深入浅出 - Android系统移植与平台开发(二) - 准备Android开发环境

    作者:唐老师,华清远见嵌入式学院讲师. 编译Android源码 关于android系统的编译,Android的官方网站上也给出了详细的说明.http://source.android.com/sour ...

  8. 深入浅出 - Android系统移植与平台开发(六)- 为Android启动加速

    作者:唐老师,华清远见嵌入式学院讲师. Android的启动速度一直以来是他的诟病,虽然现在Android设备的硬件速度越来越快,但是随着新 版本的出现,其启动速度一直都比较慢,当然,作为程序员,我们 ...

  9. 深入浅出 - Android系统移植与平台开发(七)- 初识HAL

    作者:唐老师,华清远见嵌入式学院讲师. 1. HAL的module与stub HAL(Hardware AbstractLayer)硬件抽象层是Google开发的Android系统里上层应用对底层硬件 ...

随机推荐

  1. weblogic安装以及异常解决方法【转】

    转自:http://shenjc2008.iteye.com/blog/1461253 下载地址: http://www.oracle.com/technetwork/middleware/weblo ...

  2. php curl伪造referer

    CURL方式: SOCKET方式: file_get_contents方法: 通过上面的代码,我们就把referer地址伪装为http://www.xxxx.com,你可以写一段代码: $_SERVE ...

  3. Tasker to create toggle widget for ES ftp service -- Send Intent

    To perform this mission, Tap the tab "tasks" of Tasker, create a task as below.Task: (ES F ...

  4. My安装EclipseJS代码提示(Spket插件)

    最近须要大量使用JS来开发,可是MyEclipse2014自带的JS编辑器没有代码提示的功能,开发效率有点低,所以安装了一个Spket的插件,过程很easy,SVN插件的安装比这个更简单. Spket ...

  5. PHP个人博客系统开发历程

    声明: Author:GenialX GenialX's QQ:2252065614 GenialX's URL:胡旭博客 - www.ihuxu.com 一年多曾经的某一天,我在上交实验报告时,偶然 ...

  6. ASP.NET浏览器跨域

    转载:http://www.cnblogs.com/alvinwei1024/p/4626054.html 什么是跨域? 访问同源的资源是被浏览器允许的,但是如果访问不同源的资源,浏览器默认是不允许的 ...

  7. spring mvc 下 applicationContext 和webApplicationContext

    spring中的ApplicationContexts可以被限制在不同的作用域.在web框架中,每个DispatcherServlet有它自己的WebApplicationContext,它包含了Di ...

  8. UITableView 让 cell 被选中的颜色底色快速消失,而不是一直停留在cell上

    //单元格被选中 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath ...

  9. [Linux] Systemd 入门教程:实战篇

    reference : http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-part-two.html 上一篇文章,我介绍了 Systemd ...

  10. 【BZOJ】【3612】【HEOI 2014】平衡

    DP 唉我还是too naive 这是个整数划分题…… 我想的DP方式是f[i][j][k]表示前 i 个数拼出 j 用了 k 个数的方案数…… 转移当然是比较直观…… 但是只能得30分QAQ 正确的 ...