当前位置:网站首页>Is it really hard to understand? What level of cache is the recyclerview caching mechanism?
Is it really hard to understand? What level of cache is the recyclerview caching mechanism?
2022-07-27 23:42:00 【Cattle in the yard】
0. Preface

RecyclerView Cache mechanism , It can be said that he is a regular visitor in the interview . More Than This , In use , If you understand this caching mechanism , Then we can make better use of its features for development .
that , We'll do it in a situational way , Explain RecyclerView Cache mechanism . Two common scenarios are :
1. slide RecyclerView The cache mechanism under the
2.RecyclerView Caching mechanism for initial loading process
This article will explain slide RecyclerView Next Cache mechanism
1. Cache hierarchy
Background knowledge : Responsible for recycling and reuse ViewHolder The class is Recycler, Several member variables of this class are mainly responsible for caching . Let's post some source code to see ( The following comments on the source code ( And my notes ), Very important , Remember to look carefully )
/** * A Recycler is responsible for managing scrapped or detached item views for reuse. * A "scrapped" view is a view that is still attached to its parent RecyclerView but that has been marked for removal or reuse. * * Typical use of a Recycler by a RecyclerView.LayoutManager will be to obtain views * for an adapter's data set representing the data at a given position or item ID. * If the view to be reused is considered "dirty" the adapter will be asked to rebind it. * If not, the view can be quickly reused by the LayoutManager with no further work. * Clean views that have not requested layout may be repositioned by a LayoutManager without remeasurement. */
public final class Recycler {
final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();// Store in visible range ViewHolder ( But in onLayoutChildren When , Will bring all View Will be cached here ), Reuse from here ViewHolder If position perhaps id On the corresponding , You do not need to rebind the data .
ArrayList<ViewHolder> mChangedScrap = null;// Stored within the visible range and the data has changed ViewHolder, Reuse from here ViewHolder You need to rebind the data .
final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>(); // Deposit remove Dropped ViewHolder, Reuse from here ViewHolder If position perhaps id On the corresponding , You do not need to rebind the data .
private int mRequestedCacheMax = DEFAULT_CACHE_SIZE; // The default value is 2
int mViewCacheMax = DEFAULT_CACHE_SIZE; // The default value is 2
RecycledViewPool mRecyclerPool; // Deposit remove fall , And reset the data ViewHolder, Reuse from here ViewHolder You need to rebind the data . // The default size is 5
private ViewCacheExtension mViewCacheExtension; // Custom caching
}
As for how many levels of cache are there , I don't think this problem is important . Some people say three floors , Some people say the fourth floor . Some people say three floors , Because I think the custom layer , No RecyclerView Realized , So it's not ; Some people think that Scrap Not a real cache , So it's not .
From the source code , I prefer the latter ,Scrap Not a layer of cache . Because in the source code ,mCachedViews go by the name of first-level. As for why Scrap Not the first floor , My understanding is that : Because this floor is just detach 了 , did not remove, Therefore, there is no concept of cache size in this layer , As long as the rules are met, they will join in .
// Search the first-level cache
final int cacheSize = mCachedViews.size();

2. Scene analysis : Sliding RecyclerView Caching mechanisms

adopt Android Studio Of Profiles Tools , We can see the calling process

The entrance is ouTouchEvent
By table , Briefly explain what the process above is doing ?

Through the above table , We know . The most important thing is scrollBy Called in fill The method of the . So let's see fill What are you doing ? Sliding out View Where did you end up ? Sliding in View How did you get it ?( With this question , Let's read the source code together ! Be sure to bring ), The source code only leaves the core part
int fill(RecyclerView.Recycler recycler, LayoutState layoutState,
RecyclerView.State state, boolean stopOnFocusable) {
// max offset we should set is mFastScroll + available
final int start = layoutState.mAvailable;
// The judgment of this statement block is preferred , Judge whether the current state is rolling , If so , The trigger recycleByLayoutState Method
if (layoutState.mScrollingOffset != LayoutState.SCROLLING_OFFSET_NaN) {
// TODO ugly bug fix. should not happen
if (layoutState.mAvailable < 0) {
layoutState.mScrollingOffset += layoutState.mAvailable;
}
// analysis 1---- Recycling
recycleByLayoutState(recycler, layoutState);
}
while ((layoutState.mInfinite || remainingSpace > 0) && layoutState.hasMore(state)) {
// analysis 2---- Reuse
layoutChunk(recycler, state, layoutState, layoutChunkResult);
}
}
// analysis 1---- Recycling
// Through step-by-step tracking , We found that the last call was removeAndRecycleViewAt()
public void removeAndRecycleViewAt(int index, @NonNull Recycler recycler) {
final View view = getChildAt(index);
// analysis 1-1
removeViewAt(index);
// analysis 1-2
recycler.recycleView(view);
}
// analysis 1-1
// from RecyclerView Remove a View
public void removeViewAt(int index) {
final View child = getChildAt(index);
if (child != null) {
mChildHelper.removeViewAt(index);
}
}
// analysis 1-2
// recycler.recycleView(view) The final call is recycleViewHolderInternal(holder) To recycle VH (ViewHolder)
void recycleViewHolderInternal(ViewHolder holder) {
if (forceRecycle || holder.isRecyclable()) {
// Judge whether it meets the requirements of putting in mCachedViews
if (mViewCacheMax > 0 && !holder.hasAnyOfTheFlags(ViewHolder.FLAG_INVALID| ViewHolder.FLAG_REMOVED| ViewHolder.FLAG_UPDATE| ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN)){
// Judge mCachedViews Whether is full
if (cachedViewSize >= mViewCacheMax && cachedViewSize > 0) {
// If full, subscript 0( That is, the first to join ) remove , Also add it to RecyclerPool in
recycleCachedViewAt(0);
cachedViewSize--;
}
mCachedViews.add(targetCacheIndex, holder);
cached = true;
}
// If the above conditions are not met , Save directly into RecyclerPool in
if (!cached) {
addViewHolderToRecycledViewPool(holder, true);
recycled = true;
}
}
}
// analysis 2
void layoutChunk(RecyclerView.Recycler recycler, RecyclerView.State state,
LayoutState layoutState, LayoutChunkResult result) {
// analysis 2-1
View view = layoutState.next(recycler);
if (layoutState.mScrapList == null) {
if (mShouldReverseLayout == (layoutState.mLayoutDirection
== LayoutState.LAYOUT_START)) {
// Add to RecyclerView On
addView(view);
} else {
addView(view, 0);
}
}
}
// analysis 2-1
//layoutState.next(recycler) The last thing to call is tryGetViewHolderForPositionByDeadline() This method is exactly the same Reuse The core approach
ViewHolder tryGetViewHolderForPositionByDeadline(int position,
boolean dryRun, long deadlineNs) {
// 0) If there is a changed scrap, try to find from there
// for example : We call notifyItemChanged When the method is used
if (mState.isPreLayout()) {
// If it is changed Of ViewHolder So let's start with mChangedScrap In looking for
holder = getChangedScrapViewForPosition(position);
fromScrapOrHiddenOrCache = holder != null;
}
// 1) Find by position from scrap/hidden list/cache
if (holder == null) {
// If you don't find it up there (holder == null), Then try to pass from pos stay mAttachedScrap/ mHiddenViews / mCachedViews In order to get
holder = getScrapOrHiddenOrCachedHolderForPosition(position, dryRun);
}
if (holder == null) {
// 2) Find from scrap/cache via stable ids, if exists
if (mAdapter.hasStableIds()) {
// If you don't find it up there (holder == null), Then try to pass from id stay mAttachedScrap/ mCachedViews In order to get
holder = getScrapOrCachedViewForId(mAdapter.getItemId(offsetPosition),
}
if (holder == null && mViewCacheExtension != null) {
// This is obtained from the user-defined cache , Ignore
}
// If you don't find anything on it (holder == null), Then try in RecycledViewPool In order to get
if (holder == null) { // fallback to pool
holder = getRecycledViewPool().getRecycledView(type);
if (holder != null) {
// Here is , To empty the data
holder.resetInternal();
}
}
// If in Scrap / Hidden / Cache / RecycledViewPool None of them , Then you can only create one .
if (holder == null) {
holder = mAdapter.createViewHolder(RecyclerView.this, type);
}
}
return holder;
}
3. summary
Make a summary , Before analyzing the source code , We asked three questions , Let's see what the answer is
Q: So let's see fill What are you doing ?
A: In fact, it's analysis 1( Recycling ViewHolder ) + analysis 2 ( Reuse ViewHolder )
Q: Sliding out View Where did you end up ?
A: First try to recycle to mCachedViews in , unsuccessful , Then recycle to RecycledViewPool in .
Q: Sliding in View How did you get it ?
A: If it is isPreLayout First, from mChangedScrap Trying to get .
Not obtained , Again from mAttachedScrap / mHiddenViews / mCachedViews ( adopt position ) Trying to get
Not obtained , Again from mAttachedScrap / mCachedViews ( adopt id) Trying to get
Not obtained , Again from Attempt to get... From custom cache
Not obtained , Again from RecycledViewPool Trying to get
Not obtained , Create a new ViewHolder
Recommended reading :
Really ! Interview with ALI 4 round ,RecyclerView Seven times !!!
Compose And RecyclerView How will the combination effect be ?
边栏推荐
- Error:svn: E155010: ‘/Users/.../Desktop/wrokspace/xxx‘ is scheduled for addition, but is missing
- JUC工具包学习
- 钉钉报警工具
- Join hands with Changjiang storage, jiangbolong launches the world's smallest expansion card
- File & recursion 14.1
- Calling dht11/22 temperature and humidity sensor in Proteus simulation Arduino
- 股价暴涨180.46%!国产大硅片龙头沪硅产业上市:近4年净利累计不足6000万
- 置信区间之正态
- Pentium fast system call learning
- Your list is too laggy? These four optimizations can make your list silky smooth
猜你喜欢
![[elm classification] classification of UCI data sets based on nuclear limit learning machine and limit learning machine, with matlab code](/img/bd/fe105f0af3a24ad6f220fa35bb5e8d.png)
[elm classification] classification of UCI data sets based on nuclear limit learning machine and limit learning machine, with matlab code

字符流学习14.3

远程调试 idea配置remote debug、在远程服务器的程序中,添加JVM启动参数-Xdebug

Date的使用

数据管理的重点

2022年土木,建筑与环境工程国际会议(ICCAEE 2022)

Desai wisdom number - other charts (parallel coordinate chart): family's willingness to allocate assets in the future

低代码开发前景如何,大家都真的看好低代码开发吗?

Application of user portrait in precise push of wechat official account of scientific journals

The print version of imeta | international standard ISSN is officially confirmed, and the application for dual ISSN is completed
随机推荐
After returning to mixlab for three days, "creative team" cured my spiritual internal friction
置信区间之正态
iMeta | 国际标准刊号ISSN印刷版正式确认,双ISSN申请完成
数据中台的那些“经验与陷阱”
Tita 的OKR系统与其他同类型产品,或者是共享文档等相比,有什么优势?
【CVA估值训练营】如何快速读懂上市公司年报——第四讲
JS array copy speed test 220320
Flink怎么使用Savepoint
MySQL data query (where)
Redis distributed lock
请求合并哪家强——接口请求合并的3种技巧,性能直接爆表
Sudden, wechat important notice
Using the optical fingerprint scheme under the huiding screen, Samsung Galaxy a71 5g is listed
Redis的分布式锁
Technical certification | Tupo software and Huawei cloud create a new situation of win-win cooperation
My annual salary is 1million, and I don't have clothes more than 100 yuan all over my body: saving money is the top self-discipline
进制转换方法
TSMC 3nm detail exposure: transistor density as high as 250million /mm ², Greatly improved performance and energy efficiency
C#委托用法--控制台项目,通过委托实现事件
The technology of applet container is very promising, which can greatly improve the efficiency of mobile R & D