fix recyclerview's memleak

This commit is contained in:
houzh 2024-01-24 11:18:33 +08:00
parent 64b3589ab7
commit 85a7a6e595
6 changed files with 42 additions and 25 deletions

View File

@ -51,6 +51,7 @@ int main(int argc,const char*argv[]){
w->setBackgroundColor(0xFF112233);
RecyclerView*rv=new RecyclerView(800,600);
MyAdapter*adapter=new MyAdapter();
rv->getRecycledViewPool().setMaxRecycledViews(0,64);
adapter->setHasStableIds(true);
rv->setAdapter(adapter);
DividerItemDecoration* decoration = new DividerItemDecoration(&app, LinearLayout::VERTICAL);

View File

@ -4,7 +4,6 @@
#include <widgetEx/recyclerview/linearsmoothscroller.h>
namespace cdroid{
static constexpr int _DEBUG=1;
LinearLayoutManager::LinearLayoutManager(Context* context)
:LinearLayoutManager(context, RecyclerView::DEFAULT_ORIENTATION, false){
@ -15,6 +14,7 @@ LinearLayoutManager::LinearLayoutManager(Context* context,int orientation,bool r
mLayoutState = nullptr;
mOrientationHelper = nullptr;
mLastStackFromEnd = false;
mRecycleChildrenOnDetach = true;
mAnchorInfo = new AnchorInfo();
mLayoutChunkResult = new LayoutChunkResult();
setOrientation(orientation);

View File

@ -7,6 +7,7 @@ namespace cdroid{
class GridLayoutManager;
class LinearLayoutManager:public RecyclerView::LayoutManager{
private:
static constexpr int _DEBUG=1;
static constexpr float MAX_SCROLL_FACTOR = 1.f / 3.f;
public:
static constexpr int HORIZONTAL = RecyclerView::HORIZONTAL;

View File

@ -685,7 +685,7 @@ RecyclerView::LayoutManager* RecyclerView::getLayoutManager() {
return mLayout;
}
RecyclerView::RecycledViewPool* RecyclerView::getRecycledViewPool() {
RecyclerView::RecycledViewPool& RecyclerView::getRecycledViewPool() {
return mRecycler->getRecycledViewPool();
}
@ -3539,11 +3539,24 @@ EdgeEffect* RecyclerView::EdgeEffectFactory::createEdgeEffect(RecyclerView* view
}
/////////////RecycledViewPool///////////////////
RecyclerView::RecycledViewPool::RecycledViewPool(){
}
RecyclerView::RecycledViewPool::~RecycledViewPool(){
clear();
for (int i = 0; i < mScrap.size(); i++) {
ScrapData* data = mScrap.valueAt(i);
delete data;
}
}
void RecyclerView::RecycledViewPool::clear() {
for (int i = 0; i < mScrap.size(); i++) {
ScrapData* data = mScrap.valueAt(i);
std::vector<ViewHolder*>& vhs = data->mScrapHeap;
for(int j=0;j<vhs.size();j++)delete vhs.at(j);
vhs.clear();
}
}
@ -3552,7 +3565,9 @@ void RecyclerView::RecycledViewPool::setMaxRecycledViews(int viewType, int max)
scrapData->mMaxScrap = max;
std::vector<ViewHolder*>& scrapHeap = scrapData->mScrapHeap;
while (scrapHeap.size() > max) {
scrapHeap.pop_back();//remove(scrapHeap.size() - 1);
ViewHolder*holder = scrapHeap.back();
scrapHeap.pop_back();
delete holder;
}
}
@ -3564,7 +3579,6 @@ RecyclerView::ViewHolder* RecyclerView::RecycledViewPool::getRecycledView(int vi
ScrapData* scrapData = mScrap.get(viewType);
if (scrapData != nullptr && !scrapData->mScrapHeap.empty()) {
std::vector<ViewHolder*>& scrapHeap = scrapData->mScrapHeap;
//return scrapHeap.remove(scrapHeap.size() - 1);
ViewHolder*ret = scrapHeap.back();
scrapHeap.pop_back();
return ret;
@ -3587,7 +3601,7 @@ void RecyclerView::RecycledViewPool::putRecycledView(ViewHolder* scrap) {
if (mScrap.get(viewType)->mMaxScrap <= scrapHeap.size()) {
return;
}
if (_DEBUG){// && scrapHeap.contains(scrap)) {
if (_DEBUG){
auto it =std::find(scrapHeap.begin(),scrapHeap.end(),scrap);
LOGD_IF(it!=scrapHeap.end(),"this scrap item already exists");
}
@ -3707,13 +3721,13 @@ long RecyclerView::getNanoTime() {
RecyclerView::Recycler::Recycler(RecyclerView*rv){
mRV = rv;
mViewCacheMax = DEFAULT_CACHE_SIZE;
mChangedScrap = nullptr;
mViewCacheExtension = nullptr;
mRecyclerPool = nullptr;
}
RecyclerView::Recycler::~Recycler(){
LOGD("mCachedViews.size=%d",mCachedViews.size());
delete mRecyclerPool;
}
@ -3728,12 +3742,11 @@ void RecyclerView::Recycler::setViewCacheSize(int viewCount) {
}
void RecyclerView::Recycler::updateViewCacheSize() {
int extraCache = mRV->mLayout ? mRV->mLayout->mPrefetchMaxCountObserved : 0;
const int extraCache = mRV->mLayout ? mRV->mLayout->mPrefetchMaxCountObserved : 0;
mViewCacheMax = mRequestedCacheMax + extraCache;
// first, try the views that can be recycled
for (int i = mCachedViews.size() - 1;
i >= 0 && mCachedViews.size() > mViewCacheMax; i--) {
for (int i = mCachedViews.size() - 1;i >= 0 && mCachedViews.size() > mViewCacheMax; i--) {
recycleCachedViewAt(i);
}
}
@ -3900,7 +3913,7 @@ RecyclerView::ViewHolder* RecyclerView::Recycler::tryGetViewHolderForPositionByD
}
if (holder == nullptr) { // fallback to pool
LOGD("tryGetViewHolderForPositionByDeadline(%d) fetching from shared pool",position);
holder = getRecycledViewPool()->getRecycledView(type);
holder = getRecycledViewPool().getRecycledView(type);
if (holder != nullptr) {
holder->resetInternal();
if (FORCE_INVALIDATE_DISPLAY_LIST) {
@ -4141,7 +4154,7 @@ void RecyclerView::Recycler::addViewHolderToRecycledViewPool(ViewHolder& holder,
dispatchViewRecycled(holder);
}
holder.mOwnerRecyclerView = nullptr;
getRecycledViewPool()->putRecycledView(&holder);
getRecycledViewPool().putRecycledView(&holder);
}
void RecyclerView::Recycler::quickRecycleScrapView(View* view) {
@ -4345,7 +4358,7 @@ void RecyclerView::Recycler::dispatchViewRecycled(ViewHolder& holder) {
void RecyclerView::Recycler::onAdapterChanged(Adapter* oldAdapter, Adapter* newAdapter,
bool compatibleWithPrevious) {
clear();
mRV->getRecycledViewPool()->onAdapterChanged(oldAdapter, newAdapter, compatibleWithPrevious);
mRV->getRecycledViewPool().onAdapterChanged(oldAdapter, newAdapter, compatibleWithPrevious);
}
void RecyclerView::Recycler::offsetPositionRecordsForMove(int from, int to) {
@ -4417,11 +4430,11 @@ void RecyclerView::Recycler::setRecycledViewPool(RecycledViewPool* pool) {
}
}
RecyclerView::RecycledViewPool* RecyclerView::Recycler::getRecycledViewPool() {
RecyclerView::RecycledViewPool& RecyclerView::Recycler::getRecycledViewPool() {
if (mRecyclerPool == nullptr) {
mRecyclerPool = new RecycledViewPool();
}
return mRecyclerPool;
return *mRecyclerPool;
}
void RecyclerView::Recycler::viewRangeUpdate(int positionStart, int itemCount) {
@ -4715,6 +4728,7 @@ RecyclerView::LayoutManager::LayoutManager(){
mChildHelper = nullptr;
mRecyclerView = nullptr;
mAutoMeasure = false;
mPrefetchMaxCountObserved = 0;
mPrefetchMaxObservedInInitialPrefetch = false;
}/*endof RecyclerView::LayoutManager::LayoutManager*/
@ -5988,7 +6002,6 @@ void RecyclerView::ItemDecoration::getItemOffsets(Rect& outRect, View& view,Recy
}*/
////////////////////////////////////////////////Beginning of ViewHolder///////////////////////////////////////
std::vector<Object*> RecyclerView::ViewHolder::FULLUPDATE_PAYLOADS;
RecyclerView::ViewHolder::ViewHolder(View* itemView) {
FATAL_IF(itemView == nullptr,"itemView may not be null");

View File

@ -476,7 +476,7 @@ public:
LayoutManager* getLayoutManager();
void setOnFlingListener(OnFlingListener onFlingListener);
OnFlingListener getOnFlingListener();
RecycledViewPool* getRecycledViewPool();
RecycledViewPool& getRecycledViewPool();
void setRecycledViewPool(RecycledViewPool* pool);
void setViewCacheExtension(ViewCacheExtension* extension);
void setItemViewCacheSize(int size);
@ -828,7 +828,7 @@ private:
protected:
class ScrapData {
public:
std::vector<ViewHolder*> mScrapHeap;// = new ArrayList<>();
std::vector<ViewHolder*> mScrapHeap;
int mMaxScrap = DEFAULT_MAX_SCRAP;
long mCreateRunningAverageNs = 0;
long mBindRunningAverageNs = 0;
@ -846,6 +846,8 @@ protected:
ScrapData* getScrapDataForType(int viewType);
public:
static constexpr int DEFAULT_MAX_SCRAP = 5;
RecycledViewPool();
virtual ~RecycledViewPool();
void clear();
void setMaxRecycledViews(int viewType, int max);
int getRecycledViewCount(int viewType);
@ -868,7 +870,7 @@ private:
void invalidateDisplayListInt(ViewHolder& holder);
void invalidateDisplayListInt(ViewGroup& viewGroup, bool invalidateThis);
protected:
int mViewCacheMax = DEFAULT_CACHE_SIZE;;
int mViewCacheMax = DEFAULT_CACHE_SIZE;
std::vector<ViewHolder*> mAttachedScrap;
std::vector<ViewHolder*>* mChangedScrap;
std::vector<ViewHolder*> mCachedViews;
@ -898,7 +900,7 @@ protected:
void offsetPositionRecordsForRemove(int removedFrom, int count, bool applyToPreLayout);
void setViewCacheExtension(ViewCacheExtension* extension);
void setRecycledViewPool(RecycledViewPool* pool);
RecycledViewPool* getRecycledViewPool();
RecycledViewPool& getRecycledViewPool();
void viewRangeUpdate(int positionStart, int itemCount);
void markKnownViewsInvalid();
void clearOldPositions();