深入浅出 - 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一样。尽管这样的方式创建的对象能够一直保存到手动释放。可是假设定义了大量堆对象。而忘记了释放,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实现了对强引用计数的自己主动管理
l 因为强引用计数决定了本地对象的生死。所以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的对象管理的更多相关文章
- 深入浅出 - Android系统移植与平台开发(一)
深入浅出 - Android系统移植与平台开发(一) 分类: Android移植2012-09-05 14:16 16173人阅读 评论(12) 收藏 举报 androidgitgooglejdkub ...
- 深入浅出 - Android系统移植与平台开发(五)- 编译Android源码(转)
2.3编译Android源码 Android源码体积非常庞大,由Dalvik虚拟机.Linux内核.编译系统.框架代码.Android定制C库.测试套件.系统应用程序等部分组成,在编译Android源 ...
- 深入浅出-Android系统移植与平台开发(一)- Android4.0系统的下载与编译
作者:唐老师,华清远见嵌入式学院讲师. 一.Android4.0系统的下载与编译 Android系统的下载与编译,Google的官方网站上已经给出了详细的说明,请参照Android的官方网址: htt ...
- 深入浅出 - Android系统移植与平台开发(三)- 编译并运行Android4.0模拟器
作者:唐老师,华清远见嵌入式学院讲师. 1. 编译Android模拟器 在Ubuntu下,我们可以在源码里编译出自己的模拟器及SDK等编译工具,当然这个和在windows里下载的看起来没有什么区别 ...
- 深入浅出 - Android系统移植与平台开发(十)- Android编译系统与定制Android平台系统(瘋耔修改篇二)
第四章.Android编译系统与定制Android平台系统 4.1Android编译系统 Android的源码由几十万个文件构成,这些文件之间有的相互依赖,有的又相互独立,它们按功能或类型又被放到不同 ...
- 深入浅出 - Android系统移植与平台开发(十一)- Android系统的定制(瘋耔修改篇一)
首先非常感谢原文作者为我们提供的知识库,因为有你们的贡献,我们的开发难度更显简单 原文 : http://blog.csdn.net/mr_raptor/article/details/30113 ...
- 深入浅出 - Android系统移植与平台开发(二) - 准备Android开发环境
作者:唐老师,华清远见嵌入式学院讲师. 编译Android源码 关于android系统的编译,Android的官方网站上也给出了详细的说明.http://source.android.com/sour ...
- 深入浅出 - Android系统移植与平台开发(六)- 为Android启动加速
作者:唐老师,华清远见嵌入式学院讲师. Android的启动速度一直以来是他的诟病,虽然现在Android设备的硬件速度越来越快,但是随着新 版本的出现,其启动速度一直都比较慢,当然,作为程序员,我们 ...
- 深入浅出 - Android系统移植与平台开发(七)- 初识HAL
作者:唐老师,华清远见嵌入式学院讲师. 1. HAL的module与stub HAL(Hardware AbstractLayer)硬件抽象层是Google开发的Android系统里上层应用对底层硬件 ...
随机推荐
- weblogic安装以及异常解决方法【转】
转自:http://shenjc2008.iteye.com/blog/1461253 下载地址: http://www.oracle.com/technetwork/middleware/weblo ...
- php curl伪造referer
CURL方式: SOCKET方式: file_get_contents方法: 通过上面的代码,我们就把referer地址伪装为http://www.xxxx.com,你可以写一段代码: $_SERVE ...
- 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 ...
- My安装EclipseJS代码提示(Spket插件)
最近须要大量使用JS来开发,可是MyEclipse2014自带的JS编辑器没有代码提示的功能,开发效率有点低,所以安装了一个Spket的插件,过程很easy,SVN插件的安装比这个更简单. Spket ...
- PHP个人博客系统开发历程
声明: Author:GenialX GenialX's QQ:2252065614 GenialX's URL:胡旭博客 - www.ihuxu.com 一年多曾经的某一天,我在上交实验报告时,偶然 ...
- ASP.NET浏览器跨域
转载:http://www.cnblogs.com/alvinwei1024/p/4626054.html 什么是跨域? 访问同源的资源是被浏览器允许的,但是如果访问不同源的资源,浏览器默认是不允许的 ...
- spring mvc 下 applicationContext 和webApplicationContext
spring中的ApplicationContexts可以被限制在不同的作用域.在web框架中,每个DispatcherServlet有它自己的WebApplicationContext,它包含了Di ...
- UITableView 让 cell 被选中的颜色底色快速消失,而不是一直停留在cell上
//单元格被选中 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath ...
- [Linux] Systemd 入门教程:实战篇
reference : http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-part-two.html 上一篇文章,我介绍了 Systemd ...
- 【BZOJ】【3612】【HEOI 2014】平衡
DP 唉我还是too naive 这是个整数划分题…… 我想的DP方式是f[i][j][k]表示前 i 个数拼出 j 用了 k 个数的方案数…… 转移当然是比较直观…… 但是只能得30分QAQ 正确的 ...