android中常见的类RefBase,sp,wp,Looper和handler。

RefBase是android中的基本类,类似java中的CObject类,android中的所有类都是此类的子类,当然,sp,wp是从RefBase中派生而来,这两个类的功能是利用
引用计数的方法控制对象生命周期。

(1)Refbase类

Refbase构造函数:

RefBase::RefBase()
: mRefs(new weakref_impl(this))
{
}

refbase的成员变量 mRefs,称之为RefBase类的影子对象。类型weakref_impl 。class weakref_impl是引用计数管理的管件类。分析weakref_impl的构造函数:
class weakref_impl(RefBase * base):mStrong(INITIAL_STRONG_VALUE)//强引用计数 ,初始值为0x1000000
:mWeak(0)//弱引用计数,初始化为0
:mBase(base)//该 影子对象所指的实际对象。
:mFlag(0)
:mStrongRefs(NULL)
{

}

refbase类的构造函数中完成类对象创建的同时创建出一个weakref_impl类型的影子对象。

例子分析sp,wp
代码:
calss ohter :public RefBase
{
}

int main()
{
A* PA = new A;

sp<A> spA(pA);
wp<A> wp(spA);
}

}
(2)sp类

sp的构造函数:
sp是一个模板类,

template<typename T>
sp<T>::sp (T* ohter) // ohter指的是上例中创建的类对象
:m_ptr(ohter) // 这个变量保留ohter的指针
{
if (ohter) ohter ->incStrong(this);
}
这里需要注意的是调用的这个incStrong()是RefBase的成员函数。
函数如下:

void RefBase::incStrong(const void* id) const
{
weakref_impl* const refs = mRefs;//影子对象
refs->incWeak(id);//函数调用完成后,此时弱引用数+ 1 (incWeak()中的影子对象+ 1)
refs->addStrongRef(id);//不干工作
//原子操作,结果是c保持原值0x1000000,变化是mStrong + 1
const int32_t c = android_atomic_inc(&refs->mStrong);

......

//这步处理之后mStrong变成1
android_atomic_add(-INITIAL_STRONG_VALUE, &refs->mStrong);
// 首次引用时调用onFirstRef()完成一些初始化
refs->mBase->onFirstRef();
}

sp 构造函数完成后,即通过原子操作完成强引用计数和弱引用计数均+1的操作。
(3)wp类
template<typename U> wp(U* other);
template<typename U> wp(const sp<U>& other);
template<typename U> wp(const wp<U>& other);

例子中使用是template<typename U> wp(const sp<U>& other);
模板:
template<typename T> template<typename U>
wp<T>::wp(const sp<U>& other)
: m_ptr(other.m_ptr)// 成员变量指针用来保存实际对象,指向实际对象
{
if (m_ptr) {
m_refs = m_ptr->createWeak(this);
}
}

函数调用中影子对象 m_refs = m_ptr->createWeak(this);调用的还是Refbase的函数,完成的工作是使弱引用计数+1,
这时,显示,若引用计数为2,强引用计数为1.

关于wp,sp的析构过程:

wp:
template<typename T>
wp<T>::~wp()
{
if (m_ptr) m_refs->decWeak(this);
}
decWeak()这个函数还是调用的基类refbase的函数,最终的结果是弱引用计数-1。此时干掉的只是弱引用,sp对象仍然存在,此时保持的是强弱引用计数的值都是1,就是说影子对象还存在,即表示,实际对象也存在,此时实际对象和影子对象都占据内存。

接下来是sp的析构,同理,根据源代码分析可知,此时sp的析构完成的工作是使强弱引用计数均-1。

根据分析可知,要彻底的消灭创建出来的对象,包括衍生出来的影子对象,都是由强弱引用计数控制的,当sp析构时,强引用操作的原则对象使得mStrong==0,这时导致实际对象delete this,即实际对象销毁,但是影子对象依然存在,继续分析代码可知最后随着sp的析构,影子对象也被干掉。

就是说,实际对象和影子对象的灭亡都是由其中的强弱引用计数控制的。根据代码可知,影子对象中的一个成员变量,flag,作用:当flag == 0时,强引用计数==0,导致实际对象delete,若引用计数==0,影子对象delete.

(4)wp转换成sp

wp可以转化成sp,但是sp不能转换成wp。将wp转换成sp之后,相当于又增加了一个强引用。由弱生强之后,强弱引用计数均增加,这时,强引用计数为1,弱引用计数为2.

结论:

sp 和wp这两个android中表示强弱指针的类,它们通过成员变量m_pt指向它所指向的实际对象,由于所有的android类对象都是RefBase的派生,所以,这时候可以关联到实际对象,实际对象同时创建了影子对象,在sp和wp中调用实际对象的函数,这些函数是操作的影子对象,使影子对象中的强弱引用计数增加减,最终利用强弱引用计数的变化达到实际对象和影子对象的销毁,实现了,分配空间的自动回收工作。所以说,这样的强弱指针,可以完成类对象的自动回收工作,不用手工完成,解除程序员后顾之忧。

(5)轻量级的引用计数控制类 LightRefBase

LightRefBase类是一个类模板,支持的是sp的操作,于只有一个mCount控制变量,相当于mStrong,完成的是incStrong和decStrong。


更多相关文章

  1. 类和 Json对象
  2. Android开发艺术探索——第二章:IPC机制(上)
  3. Binder---- Android(安卓)的IPC 通信机制
  4. Android实训_2020/6/16
  5. Android:线程使用来更新UI--Thread、Handler、Looper、TimerTask
  6. Android的线程使用来更新UI----Thread、Handler、Looper、TimerT
  7. 避免内存泄露
  8. Android(安卓)引用外部字体
  9. Android中Context

随机推荐

  1. Android(安卓)FFmpeg系列——7 实现快进/
  2. 在不同平台上CocosDenshion所支持的音频
  3. Android中getLocationOnScreen和getLocat
  4. Android(安卓)Retrofit2 上传文件携带参
  5. ReactNative项目从0.28升级到0.29(Android
  6. android调用手机摄像头拍照
  7. android wifi之WifiMonitor
  8. 自定义ThreadPoolExecutor
  9. Android(安卓)高德地图,显示地图,并定位当
  10. android NDK 入门之在JNI中修改java中对