經(jīng)常會在android的framework代碼中發(fā)現(xiàn)sp<xxx>和wp<xxx>這樣的指針,平時看的時候都把他當成一個普通的指針封裝過掉了,這幾天終于忍不住了,想深入了解一下。
相關(guān)的代碼:
frameworks/base/include/utils/RefBase.h
frameworks/base/libs/utils/RefBase.cpp
sp和wp都是一個模板類,看一下sp類的定義:
可以看到他確實封轉(zhuǎn)了一個原生指針T* m_ptr. 再看一下其中一個構(gòu)造函數(shù)和析構(gòu)函數(shù):
咋一看好奇怪,因為在構(gòu)造函數(shù)中調(diào)用了incStrong(),在析構(gòu)函數(shù)中調(diào)用的decStrong(),顯然是管理引用計數(shù)的函數(shù),但是sp類的中并沒有定義這兩個函數(shù),這兩個函數(shù)是在RefBase類中定義的,由此可以得出結(jié)論:
要想使用sp<T>或者wp<T>, T必需要繼承RefBase類才行。
RefBase的靜態(tài)關(guān)系如下:
其中weakref_type是RefBase的內(nèi)嵌類,weakref_impl則是weakref_type的子類,RefBase的大部分工作都是交由weakref_impl類來完成,通過RefBase的成員變量weakref_impl* const mRefs。查看其中一個sp的構(gòu)造函數(shù):
建立sp<xxx>的動態(tài)關(guān)系如下:
sp<T>
--> RefBase : incStrong()
-->weakref_impl : addStrongRef()
-->android_atomic_inc(&refs->mStrong)
可見當一個普通指針變成一個sp指針后,將會由RefBase類維護該指針的引用計數(shù),當引用為零時則自動釋放該指針指向的內(nèi)存:
wp其實是弱指針的意思,wp<T>類型不能直接對類型T進行操作,要想對T進行某種操作,必需把wp升級為sp指針,使用promote()來實現(xiàn)升級:
wp<T> weakp= new T();
sp<T> t = weakp.promote();
wp可能會在弱引用計數(shù)不為0的情況下被銷毀,執(zhí)行如下代碼:
程序打印的結(jié)果是:
D/sp-wp-sample( 225): WPTest constructor
D/sp-wp-sample( 225): promote to strong ptr...
D/sp-wp-sample( 225): first weak ptr ref callback
D/sp-wp-sample( 225): strong ptr's lifetime is just about to finish ...
D/sp-wp-sample( 225): last strong ptr ref callback
D/sp-wp-sample( 225): WPTest destructor
D/sp-wp-sample( 225): weak ptr's lifetime is just about to finish ...
D/sp-wp-sample( 225): weak ptr is out of scope.
由此可見雖然wp<WPTest >的生命周期還沒有結(jié)束,但是因為升級為sp<WPTest >后,sp<WPTest >的強引用計數(shù)為0,導致WPTest 被銷毀,當強引用為0而弱引用不為0時,WPTest 銷毀時,基類RefBase的mRefs指向的weakref_impl類并沒有釋放,從而保證了弱引用可以繼續(xù)起作用,這點可以從RefBase的析構(gòu)函數(shù)中看出來:
不過也可以改變這一行為,我們修改一下WPTest的構(gòu)造函數(shù):
這時的打印結(jié)果是:
D/sp-wp-sample( 217): WPTest constructor
D/sp-wp-sample( 217): promote to strong ptr...
D/sp-wp-sample( 217): first weak ptr ref callbac
D/sp-wp-sample( 217): strong ptr's lifetime is j
D/sp-wp-sample( 217): last strong ptr ref callba
D/sp-wp-sample( 217): weak ptr's lifetime is j
D/sp-wp-sample( 217): last weak ptr ref callback
D/sp-wp-sample( 217): WPTest destructor
D/sp-wp-sample( 217): weak ptr is out of scope.
可以看出現(xiàn)在只有當強引用和弱引用的計數(shù)都為0時,WPTest對象才會被銷毀。
聯(lián)系客服