聊聊RecyclerView新出的ConcatAdapter如何使用
码个蛋
共 8110字,需浏览 17分钟
·
2021-07-02 14:49
听说有品位的程序员都关注了
1.前言
增加了ConcatAdapter:这个Adapter方便地让我们在一个RecyclerView中连接多个Adapters。 支持延迟恢复状态:RecyclerView现在支持当内容加载出来后恢复状态。
2.简单使用
2.1 不使用ConcatAdapter实现
2.1 不使用ConcatAdapter实现
2.2 使用ConcatAdapter实现
2.3 优势和劣势
3. 高级进阶
public ConcatAdapter(Adapter<? extends ViewHolder>... adapters) {
this(Config.DEFAULT, adapters);
}
public ConcatAdapter(Config config, Adapter<? extends ViewHolder>... adapters) {
this(config, Arrays.asList(adapters));
}
Config(boolean isolateViewTypes, StableIdMode stableIdMode) {
this.isolateViewTypes = isolateViewTypes;
this.stableIdMode = stableIdMode;
}
public static final Config DEFAULT = new Config(true, NO_STABLE_IDS);
3.1 不共用缓存
RedAdapter redAdapter1 = xxx;
OrangeAdapter orangerAdapter = xxx;
BlueAdapter blueAdapter = xxx;
RedAdapter redAdapter2 = xxx;
ConcatAdapter concatenated = new ConcatAdapter(redAdapter1, orangerAdapter,blueAdapter,redAdapter2);
recyclerView.setAdapter(concatenated);
3.2 共用缓存
RedAdapter redAdapter1 = xxx;
OrangeAdapter orangerAdapter = xxx;
BlueAdapter blueAdapter = xxx;
RedAdapter redAdapter2 = xxx;
//isolateViewTypes为false
ConcatAdapter.Config config = ConcatAdapter.Config.Builder().setIsolateViewTypes(false).build()
ConcatAdapter concatenated = new ConcatAdapter(config, redAdapter1, orangerAdapter,blueAdapter,redAdapter2);
recyclerView.setAdapter(concatenated);
4. 爬坑
class ConcatAdapterDemoActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_concat_adapter_demo)
val recyclerView = findViewById<RecyclerView>(R.id.recyclerview)
recyclerView.layoutManager = LinearLayoutManager(this)
val config = ConcatAdapter.Config.Builder().setIsolateViewTypes(false).build()
recyclerView.adapter = ConcatAdapter(
config,
TextAdapter(),
ButtonAdapter()
)
}
}
recyclerView.adapter = ConcatAdapter(
config,
TextAdapter(),
ButtonAdapter(),
TextAdapter()
)
5. 原理
ConcatAdapter.getItemViewType()
//ConcatAdapter.java
@Override
public int getItemViewType(int position) {
return mController.getItemViewType(position);
}
ConcatAdapterController.getItemViewType(int globalPosition)
//ConcatAdapterController.java
public int getItemViewType(int globalPosition) {
//根据globalPosition找到对应的子Adapter的Wrapper
WrapperAndLocalPosition wrapperAndPos = findWrapperAndLocalPosition(globalPosition);
int itemViewType = wrapperAndPos.mWrapper.getItemViewType(wrapperAndPos.mLocalPosition);
releaseWrapperAndLocalPosition(wrapperAndPos);
return itemViewType;
}
NestedAdapterWrapper.getItemViewType(int localPosition)
int getItemViewType(int localPosition) {
return mViewTypeLookup.localToGlobal(adapter.getItemViewType(localPosition));
}
IsolatedViewTypeStorage$WrapperViewTypeLookup.localToGlobal()
@Override
public int localToGlobal(int localType) {
int index = mLocalToGlobalMapping.indexOfKey(localType);
if (index > -1) {
return mLocalToGlobalMapping.valueAt(index);
}
// get a new key.
int globalType = obtainViewType(mWrapper);
mLocalToGlobalMapping.put(localType, globalType);
mGlobalToLocalMapping.put(globalType, localType);
return globalType;
}
IsolatedViewTypeStorage$WrapperViewTypeLookup。从代码可以看出在不共享缓存池的情况下。「子Adapter的viewType会从0递增对应」
int mNextViewType = 0;
int obtainViewType(NestedAdapterWrapper wrapper) {
int nextId = mNextViewType++;
mGlobalTypeToWrapper.put(nextId, wrapper);
return nextId;
}
isolateViewTypes为true的情况下。会使用SharedIdRangeViewTypeStorage$WrapperViewTypeLookup。我们看到 localType和globalType相等。
@Override
public int localToGlobal(int localType) {
// register it first
List<NestedAdapterWrapper> wrappers = mGlobalTypeToWrapper.get(
localType);
if (wrappers == null) {
wrappers = new ArrayList<>();
mGlobalTypeToWrapper.put(localType, wrappers);
}
if (!wrappers.contains(mWrapper)) {
wrappers.add(mWrapper);
}
return localType;
}
@Override
public int globalToLocal(int globalType) {
return globalType;
}
码个蛋专属活动:打卡入口
为什么要做这个活动?
关注「码个蛋」,一起打卡成长
评论