当前位置:网站首页>Viewpager pageradapter notifydatasetchanged invalid problem
Viewpager pageradapter notifydatasetchanged invalid problem
2022-07-05 09:36:00 【Black Mountain demon 2018】
As we all know , Whether we are using RecyclerView still ListView when , After updating the data source, it will call adapter Of notifyDataSetChanged() Method to update the view . and PagerAdapter Namely ViewPager The use of adapter, But in practice , It is found that updating the data source does not necessarily update the view .
Let's take a look at Google's right PagerAdapter This method of notifyDataSetChanged() The definition of
Personally, I don't think the definition of Google's method is a good explanation for the problems I encounter in my work , So try the source code ...
/**
* This method should be called by the application if the data backing this adapter has changed
* and associated views should update.
*/
public void notifyDataSetChanged() {
synchronized (this) {
if (mViewPagerObserver != null) {
mViewPagerObserver.onChanged();
}
}
mObservable.notifyChanged();
}
At first glance, it is the observer mode , Here we only focus on mViewPagerObserver, See where it is assigned .
void setViewPagerObserver(DataSetObserver observer) {
synchronized (this) {
mViewPagerObserver = observer;
}
}
Let's see where this method is called .
/** * Set a PagerAdapter that will supply views for this pager as needed. * * @param adapter Adapter to use */ public void setAdapter(PagerAdapter adapter) { if (mAdapter != null) { mAdapter.setViewPagerObserver(null); mAdapter.startUpdate(this); for (int i = 0; i < mItems.size(); i++) { final ItemInfo ii = mItems.get(i); mAdapter.destroyItem(this, ii.position, ii.object); } mAdapter.finishUpdate(this); mItems.clear(); removeNonDecorViews(); mCurItem = 0; scrollTo(0, 0); } final PagerAdapter oldAdapter = mAdapter; mAdapter = adapter; mExpectedAdapterCount = 0; if (mAdapter != null) { if (mObserver == null) { mObserver = new PagerObserver(); } mAdapter.setViewPagerObserver(mObserver); mPopulatePending = false; final boolean wasFirstLayout = mFirstLayout; mFirstLayout = true; mExpectedAdapterCount = mAdapter.getCount(); if (mRestoredCurItem >= 0) { mAdapter.restoreState(mRestoredAdapterState, mRestoredClassLoader); setCurrentItemInternal(mRestoredCurItem, false, true); mRestoredCurItem = -1; mRestoredAdapterState = null; mRestoredClassLoader = null; } else if (!wasFirstLayout) { populate(); } else { requestLayout(); } } // Dispatch the change to any listeners if (mAdapterChangeListeners != null && !mAdapterChangeListeners.isEmpty()) { for (int i = 0, count = mAdapterChangeListeners.size(); i < count; i++) { mAdapterChangeListeners.get(i).onAdapterChanged(this, oldAdapter, adapter); } } }
In the above code, it is seen in setAdapter Assign values in this method , And see mObserver = new PagerObserver();mObserver This object is also created in this method , I want to see others PagerObserver This class , Is a private inner class .
private class PagerObserver extends DataSetObserver { PagerObserver() { } @Override public void onChanged() { dataSetChanged(); } @Override public void onInvalidated() { dataSetChanged(); } }
Now it's clear ,notifyDataSetChanged() In the method mViewPagerObserver.onChanged() Execution is dataSetChanged() Method , Let's see dataSetChanged() This method .
void dataSetChanged() {
// This method only gets called if our observer is attached, so mAdapter is non-null.
final int adapterCount = mAdapter.getCount();
mExpectedAdapterCount = adapterCount;
boolean needPopulate = mItems.size() < mOffscreenPageLimit * 2 + 1
&& mItems.size() < adapterCount;
int newCurrItem = mCurItem;
boolean isUpdating = false;
for (int i = 0; i < mItems.size(); i++) {
final ItemInfo ii = mItems.get(i);
final int newPos = mAdapter.getItemPosition(ii.object);
if (newPos == PagerAdapter.POSITION_UNCHANGED) {
continue;
}
if (newPos == PagerAdapter.POSITION_NONE) {
mItems.remove(i);
i--;
if (!isUpdating) {
mAdapter.startUpdate(this);
isUpdating = true;
}
mAdapter.destroyItem(this, ii.position, ii.object);
needPopulate = true;
if (mCurItem == ii.position) {
// Keep the current item in the valid range
newCurrItem = Math.max(0, Math.min(mCurItem, adapterCount - 1));
needPopulate = true;
}
continue;
}
if (ii.position != newPos) {
if (ii.position == mCurItem) {
// Our current item changed position. Follow it.
newCurrItem = newPos;
}
ii.position = newPos;
needPopulate = true;
}
}
if (isUpdating) {
mAdapter.finishUpdate(this);
}
Collections.sort(mItems, COMPARATOR);
if (needPopulate) {
// Reset our known page widths; populate will recompute them.
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (!lp.isDecor) {
lp.widthFactor = 0.f;
}
}
setCurrentItemInternal(newCurrItem, false, true);
requestLayout();
}
}
See the red mark , I want to see others getItemPosition() This method ,
/** * Called when the host view is attempting to determine if an item's position * has changed. Returns {@link #POSITION_UNCHANGED} if the position of the given * item has not changed or {@link #POSITION_NONE} if the item is no longer present * in the adapter. * * <p>The default implementation assumes that items will never * change position and always returns {@link #POSITION_UNCHANGED}. * * @param object Object representing an item, previously returned by a call to * {@link #instantiateItem(View, int)}. * @return object's new position index from [0, {@link #getCount()}), * {@link #POSITION_UNCHANGED} if the object's position has not changed, * or {@link #POSITION_NONE} if the item is no longer present. */ public int getItemPosition(Object object) { return POSITION_UNCHANGED; }
Default return POSITION_UNCHANGED, This leads to the update of the data source , But the view doesn't change .
So my solution is to rewrite getItemPosition() This method , To return to POSITION_NONE. Of course, this method costs a lot of system , Do it every time destroyItem() Method , If the amount of data is small , It will cause a lot of unnecessary expenses .
边栏推荐
- 一文详解图对比学习(GNN+CL)的一般流程和最新研究趋势
- 图神经网络+对比学习,下一步去哪?
- 【el-table如何禁用】
- High performance spark_ Transformation performance
- NIPS2021 | 超越GraphCL,GNN+对比学习的节点分类新SOTA
- [ctfhub] Title cookie:hello guest only admin can get flag. (cookie spoofing, authentication, forgery)
- LeetCode 503. Next bigger Element II
- 初识结构体
- [how to disable El table]
- Wxml template syntax
猜你喜欢
Information and entropy, all you want to know is here
Figure neural network + comparative learning, where to go next?
The popularity of B2B2C continues to rise. What are the benefits of enterprises doing multi-user mall system?
Can't find the activitymainbinding class? The pit I stepped on when I just learned databinding
An article takes you into the world of cookies, sessions, and tokens
How to choose the right chain management software?
项目实战 | Excel导出功能
[team PK competition] the task of this week has been opened | question answering challenge to consolidate the knowledge of commodity details
Go 语言使用 MySQL 的常见故障分析和应对方法
Unity SKFramework框架(二十二)、Runtime Console 运行时调试工具
随机推荐
Deep understanding of C language pointer
Project practice | excel export function
Applet global style configuration window
代码语言的魅力
揭秘百度智能测试在测试自动执行领域实践
c语言指针深入理解
Node の MongoDB Driver
一文详解图对比学习(GNN+CL)的一般流程和最新研究趋势
一次 Keepalived 高可用的事故,让我重学了一遍它
Unity skframework framework (XXIII), minimap small map tool
What should we pay attention to when entering the community e-commerce business?
观测云与 TDengine 达成深度合作,优化企业上云体验
LeetCode 31. 下一个排列
Hosting environment API
OpenGL - Coordinate Systems
云计算技术热点
Composition of applet code
Alibaba's ten-year test brings you into the world of APP testing
Unity SKFramework框架(二十四)、Avatar Controller 第三人称控制
STM32 simple multi-level menu (array table lookup method)