[Turn] Detailed explanation ViewPager calling FragmentPagerAdapter.notifyDataSetChanged() cannot update Fragment

Reprinted from
http://www.blog4app.com/?p=62

My question: Fragment displays the pictures down from the network, and the list is used when the list is changed from one picture to multiple pictures.


@Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

It can solve the problem,




but there is only one picture in the list. When it needs to be updated to another picture, if it doesn't work
, it needs to be reloaded.
public Object instantiateItem(ViewGroup container, int position)
The data in the fragment is updated to achieve this.
Thanks to




original blogger for sharing the first part: the reason for the phenomenon The

code is implemented by default.
After FragmentPagerAdapter calls notifyDataSetChanged, execute mObservable.notifyChanged(). The initialization of the mObservable object is assigned when ViewPager calls setAdapter, and the corresponding class is called PagerObserver. The dataSetChanged method of PagerObserver is as follows:
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;
            }
        }


The default getItemPosition implementation of PagerAdapter is return POSITION_UNCHANGED. So calling the notifyDataSetChanged method will not refresh the Fragment.

Part 2: Solution

In order to make Fragment repaint, the getItemPositon method of FragmentPagerAdapter must be overloaded and modified to return POSITION_NONE. In this way, all previous Fragments will be detached.
@Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }


If you follow the steps above and call notifyDataSetChanged and the list data bit is empty, then the result is what you want to see. However, if the data of the list is modified on the original basis, the information displayed on the Fragment you see as a result is still the previous data.

Part 3: Reasons for

Fragment
private static String makeFragmentName(int viewId, long id) {
        return "android:switcher:" + viewId + ":" + id;
    }

After refreshing, call the instantiateItem method of FragmentPagerAdapgter, find the detached Fragment through findFragmentByTag, then execute the attach method of the Fragment, and finally execute the Fragment's life cycle again, so the data you see on the Fragment is still the old data.

Part 4: Solution

As described in Part 3, if Fragment you go to a new Fragment through the getItem method, and then the data is set into it through setArgument. Then after executing the attach method of the modified Fragment again, the data obtained is still the old data. The solution is to call the Fragment's custom method resetFragmentData() in the instantiateItem method to replace the old data. Note: resetFragmentData can only be used for data replacement, not to update the view directly. The update of the View is still executed after calling the attach method and continuing to the onActivityCreated method to refresh the View.

public class CarTypeListAdapter extends FragmentPagerAdapter {
 
    private final ArrayList<CarTypeListMinPriceResult.CarTypeMinPrice> mRecList;
    protected ImageWorker mImageFetcher;
 
    public CarTypeListAdapter(FragmentManager fm, ArrayList<CarTypeListMinPriceResult.CarTypeMinPrice> recList, ImageWorker worker) {
        super (fm);
        this.mRecList = recList;
        this.mImageFetcher = worker;
    }
 
    @Override
    public Fragment getItem(int position) {
        CarTypeInfoFragment imageFragment = CarTypeInfoFragment.newInstance(mRecList.get(position), mImageFetcher);
        return imageFragment;
    }
 
    public Object instantiateItem(ViewGroup container, int position) {
        CarTypeInfoFragment f = (CarTypeInfoFragment)super.instantiateItem(container, position);
        if(!QArrays.isEmpty(mRecList) && position >=0 && position < mRecList.size()){
            CarTypeListMinPriceResult.CarTypeMinPrice p = mRecList.get(position);
            if(p != null){
                f.resetFragmentData(p);
            }
        }
 
        return f;
    }
 
    @Override
     public int getItemPosition(Object object) {
        return POSITION_NONE;
    }
 
    @Override
    public int getCount() {
        return mRecList == null ? 0 : mRecList.size();
    }
}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327042426&siteId=291194637