当前位置:网站首页>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 .
边栏推荐
- 【PyTorch Bug】RuntimeError: Boolean value of Tensor with more than one value is ambiguous
- 小程序启动性能优化实践
- OpenGL - Lighting
- Svg optimization by svgo
- Kotlin introductory notes (VI) interface and function visibility modifiers
- [team PK competition] the task of this week has been opened | question answering challenge to consolidate the knowledge of commodity details
- 22-07-04 西安 尚好房-项目经验总结(01)
- Nips2021 | new SOTA for node classification beyond graphcl, gnn+ comparative learning
- C language - input array two-dimensional array a from the keyboard, and put 3 in a × 5. The elements in the third column of the matrix are moved to the left to the 0 column, and the element rows in ea
- Understanding of smt32h7 series DMA and DMAMUX
猜你喜欢

Shutter uses overlay to realize global pop-up

植物大战僵尸Scratch

22-07-04 Xi'an Shanghao housing project experience summary (01)

The popularity of B2B2C continues to rise. What are the benefits of enterprises doing multi-user mall system?

Go 语言使用 MySQL 的常见故障分析和应对方法

A keepalived high availability accident made me learn it again

Unity skframework framework (24), avatar controller third person control

Using request headers to develop multi terminal applications

Applet network data request

Understanding of smt32h7 series DMA and DMAMUX
随机推荐
高性能Spark_transformation性能
OpenGL - Coordinate Systems
【el-table如何禁用】
[object array A and object array B take out different elements of ID and assign them to the new array]
Project practice | excel export function
【PyTorch Bug】RuntimeError: Boolean value of Tensor with more than one value is ambiguous
SQL learning - case when then else
植物大战僵尸Scratch
[hungry dynamic table]
基于宽表的数据建模应用
LeetCode 496. Next larger element I
一文读懂TDengine的窗口查询功能
MySQL installation configuration and creation of databases and tables
百度APP 基于Pipeline as Code的持续集成实践
百度评论中台的设计与探索
【js 根据对象数组中的属性进行排序】
Dry goods sorting! How about the development trend of ERP in the manufacturing industry? It's enough to read this article
[sorting of object array]
First understanding of structure
Unity SKFramework框架(二十三)、MiniMap 小地图工具