💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
客户端拿到的游标对象的真实类型是CursorWrapperInner,其close函数的代码如下: **ContentResolver.java::CursorWrapperInner.close** ~~~ public void close() { super.close();//调用基类的close函数 //撤销客户端进程和目标CP进程的亲密关系 ContentResolver.this.releaseProvider(mContentProvider); mProviderReleased = true; if(mCloseGuard != null) mCloseGuard.close(); } ~~~ 下面来看CursorWrapperInner的基类CursorWrapper的close函数。须提醒读者注意,后文对函数分析会频繁从基类转到子类,又从子类转到基类。造成这种局面的原因就是对类封装得太利害的结果。 **CursorWrapper.java::close** ~~~ public void close() { mCursor.close(); //mCursor指向BulkCursorToCursorAdaptor } ~~~ BulkCursorToCursorAdaptorclose的代码如下: **BulkCurosrToCursorAdaptor.java::close** ~~~ public void close() { super.close();//①再次调用基类close函数,该函数会释放本地创建的CursorWindow资源 if(mBulkCursor != null) { try { mBulkCursor.close();//②调用远端对象的close函数 }...... finally { mBulkCursor = null; } } } ~~~ 对于Cursor close函数来说,笔者更关注其中所包含的CursorWindow资源是如何释放的。根据以上代码中的注释可知,BulkCurosrToCursorAdaptor的close调用的基类close函数会释放CursorWindow。 接下来来看super.close这个函数。这个close由BulkCurosrToCursorAdaptor的父类AbstractWindowedCursor的父类AbstractCursor实现,其代码如下: **AbstractCursor.java::close** ~~~ public void close() { mClosed =true; mContentObservable.unregisterAll(); onDeactivateOrClose();//调用子类实现的onDeactivateOrClose函数 } ~~~ onDeactivateOrClose由AbstractCursor的子类AbstractWindowedCursor实现,代码如下: **AbstractWindowedCursor.java::onDeactivateOrClose** ~~~ protected void onDeactivateOrClose() { //又调用基类即AbstractCursor的onDeactivateOrClose函数 super.onDeactivateOrClose(); closeWindow();//释放CursorWindow资源 } ~~~ close函数涉及的调用居然在派生树中如此反复出现,这让人无奈-!后面还会碰到类似的做法,读者务必保持镇静。 **AbstractWindowedCursor.java::close** ~~~ protected void closeWindow() { if(mWindow != null) { mWindow.close();//调用CurosrWindow的close函数 mWindow = null; } } ~~~ CursorWindow从SQLiteClosable派生,根据前面的介绍,释放SQLiteClosable代表的资源会利用引用计数来控制,这是如何实现的呢?来看代码: **CursorWindow.java::close** ~~~ public void close() { releaseReference();//减少一次引用计数 } ~~~ releaseReference由CursorWindow的基类SQLiteClosable实现,其代码如下: **SQLiteClosable.java::releaseReference** ~~~ public void releaseReference() { booleanrefCountIsZero = false; synchronized(this) { refCountIsZero = --mReferenceCount == 0; } if(refCountIsZero) {//当引用计数减为0时,就可以真正释放资源了 onAllReferencesReleased();//调用子类实现的onAllReferencesReleased函数 } } ~~~ 资源释放的工作由子类实现的onAllReferencesReleased完成,对CursorWindow来说,该函数的代码如下: **CursorWindow.java::onAllReferencesReleased** ~~~ protected void onAllReferencesReleased() { dispose();//调用dispose } private void dispose() { if(mCloseGuard != null) { mCloseGuard.close(); } if(mWindowPtr != 0) { recordClosingOfWindow(mWindowPtr); //调用nativeDispose函数,该函数内部会释放Native层的CursorWindow对象 //至此,客户端获取的那块共享内存就彻底释放干净了 nativeDispose(mWindowPtr); mWindowPtr = 0; } } ~~~ 至此,客户端游标对象的close函数已分析完毕,不知读者看完整个流程后有何感想。