mirror of
https://gitee.com/houstudio/Cdroid.git
synced 2024-12-04 21:27:41 +08:00
fix recyclerview's memleak
This commit is contained in:
parent
64b3589ab7
commit
85a7a6e595
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user