331

ViewPagerのコンテンツを更新できません。

FragmentPagerAdapterクラスのメソッドinstantiateItem()およびgetItem()の正しい使用法は何ですか?

getItem()のみを使用して、フラグメントをインスタンス化して返していました。

@Override
public Fragment getItem(int position) {
    return new MyFragment(context, paramters);
}

これはうまくいきました。内容を変更できない場合を除きます。

だから私はこれを見つけました:ViewPagerPagerAdapterがビューを更新していません

「私のアプローチは、instantiateItem()メソッドのインスタンス化されたビューにsetTag()メソッドを使用することです。」

これを行うために、instantiateItem()を実装したいと思います。しかし、何を返す必要があるのか​​(タイプはObject)、getItem(int position)との関係はわかりませんか?

私はリファレンスを読みました:

  • public abstract Fragment getItem(int position)

    指定された位置に関連付けられているフラグメントを返します。

  • public Object instanceiateItem(ViewGroupコンテナー、int位置)

    指定された位置のページを作成します。アダプターは、ここで指定されたコンテナーにビューを追加する責任がありますが、finishUpdate(ViewGroup)から戻るまでにこれが確実に行われるようにする必要があります。パラメーター

    コンテナページが表示される包含ビュー。positionインスタンス化されるページ位置。

    戻り値

    新しいページを表すオブジェクトを返します。これはビューである必要はありませんが、ページの他のコンテナにすることができます。

しかし、私はまだそれを取得していません。

これが私のコードです。サポートパッケージv4を使用しています。

ViewPagerTest

public class ViewPagerTest extends FragmentActivity {
    private ViewPager pager;
    private MyFragmentAdapter adapter; 

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pager1);

        pager = (ViewPager)findViewById(R.id.slider);

        String[] data = {"page1", "page2", "page3", "page4", "page5", "page6"};

        adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        pager.setAdapter(adapter);

        ((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                reload();
            }
        });
    }

    private void reload() {
        String[] data = {"changed1", "changed2", "changed3", "changed4", "changed5", "changed6"};
        //adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        adapter.setData(data);
        adapter.notifyDataSetChanged();
        pager.invalidate();

        //pager.setCurrentItem(0);
    }
}

MyFragmentAdapter

class MyFragmentAdapter extends FragmentPagerAdapter {
    private int slideCount;
    private Context context;
    private String[] data;

    public MyFragmentAdapter(FragmentManager fm, int slideCount, Context context, String[] data) {
        super(fm);
        this.slideCount = slideCount;
        this.context = context;
        this.data = data;
    }

    @Override
    public Fragment getItem(int position) {
        return new MyFragment(data[position], context);
    }

    @Override
    public int getCount() {
        return slideCount;
    }

    public void setData(String[] data) {
        this.data = data;
    }

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

MyFragment

public final class MyFragment extends Fragment {
    private String text;

    public MyFragment(String text, Context context) {
        this.text = text;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.slide, null);
        ((TextView)view.findViewById(R.id.text)).setText(text);

        return view;
    }
}

同様の問題を抱えている人もいますが、回答はありません http://www.mail-archive.com/android-developers@googlegroups.com/msg200477.html

4

21 に答える 21

622

FragmentPagerAdapterまたはFragmentStatePagerAdapterを使用する場合はgetItem()、まったく触れずに、単独で処理するのが最善instantiateItem()です。instantiateItem()PagerAdapterの---インターフェイスは、FragmentPagerAdapterがはるかに単純destroyItem()なインターフェイスisViewFromObject()を実装するために使用する低レベルのインターフェイスgetItem()です。

これに入る前に、私はそれを明確にする必要があります

表示されている実際のフラグメントを切り替える場合は、FragmentPagerAdapterを避け、FragmentStatePagerAdapterを使用する必要があります。

この回答の以前のバージョンでは、例としてFragmentPagerAdapterを使用するという間違いがありました。これは、FragmentPagerAdapterが最初に表示された後にフラグメントを破棄しないため、機能しません。

リンクした投稿に記載されている回避策はお勧めしませんsetTag()findViewWithTag()ご存知のように、フラグメントを使用するsetTag()findViewWithTag()機能しないため、適切な一致ではありません。

正しい解決策は、をオーバーライドすることgetItemPosition()です。がnotifyDataSetChanged()呼び出されると、ViewPagerはgetItemPosition()アダプター内のすべてのアイテムを呼び出して、それらを別の位置に移動する必要があるか、削除する必要があるかを確認します。

デフォルトでは、をgetItemPosition()返しますPOSITION_UNCHANGED。これは、「このオブジェクトは、現在の場所では問題ありません。破棄したり削除したりしないでください」という意味です。戻るPOSITION_NONEと、代わりに「このオブジェクトは表示しているアイテムではなくなりました。削除してください」と言うことで問題が修正されます。したがって、アダプタ内のすべてのアイテムを削除して再作成する効果があります。

これは完全に正当な修正です!この修正により、notifyDataSetChangedは、ビューのリサイクルなしで通常のアダプターのように動作します。この修正を実装し、パフォーマンスが満足のいくものであれば、レースに出かけることができます。仕事は終わりました。

より良いパフォーマンスが必要な場合は、より優れたgetItemPosition()実装を使用できます。文字列のリストからフラグメントを作成するポケットベルの例を次に示します。

ViewPager pager = /* get my ViewPager */;
// assume this actually has stuff in it
final ArrayList<String> titles = new ArrayList<String>();

FragmentManager fm = getSupportFragmentManager();
pager.setAdapter(new FragmentStatePagerAdapter(fm) {
    public int getCount() {
        return titles.size();
    }

    public Fragment getItem(int position) {
        MyFragment fragment = new MyFragment();
        fragment.setTitle(titles.get(position));
        return fragment;
    }

    public int getItemPosition(Object item) {
        MyFragment fragment = (MyFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        if (position >= 0) {
            return position;
        } else {
            return POSITION_NONE;
        }
    }
});

この実装では、新しいタイトルを表示するフラグメントのみが表示されます。リストに残っているタイトルを表示しているフラグメントは、代わりにリスト内の新しい位置に移動され、リストにまったく含まれていないタイトルを持つフラグメントは破棄されます。

フラグメントが再作成されていないが、とにかく更新する必要がある場合はどうなりますか?生きているフラグメントへの更新は、フラグメント自体によって最も適切に処理されます。それは、結局のところ、フラグメントを持つことの利点です-それはそれ自身のコントローラーです。フラグメントは、でリスナーまたはオブザーバーを別のオブジェクトに追加しonCreate()、でそれを削除してonDestroy()、更新自体を管理できます。getItem()ListViewまたは他のAdapterViewタイプのアダプターのように、すべての更新コードを内部に配置する必要はありません。

最後にもう1つ、FragmentPagerAdapterがフラグメントを破棄しないからといって、getItemPositionがFragmentPagerAdapterで完全に役に立たないというわけではありません。このコールバックを使用して、ViewPagerでフラグメントを並べ替えることができます。ただし、FragmentManagerから完全に削除されることはありません。

于 2012-06-01T14:22:07.693 に答える
149

POSITION_NONEから戻ってフルビューのgetItemPosition()レクリエーションを引き起こす代わりに、次のようにします。

//call this method to update fragments in ViewPager dynamically
public void update(UpdateData xyzData) {
    this.updateData = xyzData;
    notifyDataSetChanged();
}

@Override
public int getItemPosition(Object object) {
    if (object instanceof UpdateableFragment) {
        ((UpdateableFragment) object).update(updateData);
    }
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);
}

フラグメントはUpdateableFragmentインターフェースを実装する必要があります。

public class SomeFragment extends Fragment implements
    UpdateableFragment{

    @Override
    public void update(UpdateData xyzData) {
         // this method will be called for every fragment in viewpager
         // so check if update is for this fragment
         if(forMe(xyzData)) {
           // do whatever you want to update your UI
         }
    }
}

およびインターフェース:

public interface UpdateableFragment {
   public void update(UpdateData xyzData);
}

データクラス:

public class UpdateData {
    //whatever you want here
}
于 2013-07-25T10:40:15.743 に答える
27

for those who still face the same problem which i faced before when i have a ViewPager with 7 fragments. the default for these fragments to load the English content from API service but the problem here that i want to change the language from settings activity and after finish settings activity i want ViewPager in main activity to refresh the fragments to match the language selection from the user and load the Arabic content if user chooses Arabic here what i did to work from the first time

1- You must use FragmentStatePagerAdapter as mentioned above.

2- on mainActivity i override the onResume and did the following

if (!(mPagerAdapter == null)) {
    mPagerAdapter.notifyDataSetChanged();
}

3-i overrided the getItemPosition() in mPagerAdapter and make it return POSITION_NONE.

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

works like charm

于 2014-12-11T11:40:33.487 に答える
16
于 2013-08-08T06:51:35.653 に答える
13

destroyDrawingCache()コードの後でViewPagerを試してくださいnotifyDataSetChanged()

于 2013-07-09T09:03:34.290 に答える
11

After hours of frustration while trying all the above solutions to overcome this problem and also trying many solutions on other similar questions like this, this and this which all FAILED with me to solve this problem and to make the ViewPager to destroy the old Fragment and fill the pager with the new Fragments. I have solved the problem as following:

1) Make the ViewPager class to extends FragmentPagerAdapter as following:

 public class myPagerAdapter extends FragmentPagerAdapter {

2) Create an Item for the ViewPager that store the title and the fragment as following:

public class PagerItem {
private String mTitle;
private Fragment mFragment;


public PagerItem(String mTitle, Fragment mFragment) {
    this.mTitle = mTitle;
    this.mFragment = mFragment;
}
public String getTitle() {
    return mTitle;
}
public Fragment getFragment() {
    return mFragment;
}
public void setTitle(String mTitle) {
    this.mTitle = mTitle;
}

public void setFragment(Fragment mFragment) {
    this.mFragment = mFragment;
}

}

3) Make the constructor of the ViewPager take my FragmentManager instance to store it in my class as following:

private FragmentManager mFragmentManager;
private ArrayList<PagerItem> mPagerItems;

public MyPagerAdapter(FragmentManager fragmentManager, ArrayList<PagerItem> pagerItems) {
    super(fragmentManager);
    mFragmentManager = fragmentManager;
    mPagerItems = pagerItems;
}

4) Create a method to re-set the adapter data with the new data by deleting all the previous fragment from the fragmentManager itself directly to make the adapter to set the new fragment from the new list again as following:

public void setPagerItems(ArrayList<PagerItem> pagerItems) {
    if (mPagerItems != null)
        for (int i = 0; i < mPagerItems.size(); i++) {
            mFragmentManager.beginTransaction().remove(mPagerItems.get(i).getFragment()).commit();
        }
    mPagerItems = pagerItems;
}

5) From the container Activity or Fragment do not re-initialize the adapter with the new data. Set the new data through the method setPagerItems with the new data as following:

ArrayList<PagerItem> pagerItems = new ArrayList<PagerItem>();
    pagerItems.add(new PagerItem("Fragment1", new MyFragment1()));
    pagerItems.add(new PagerItem("Fragment2", new MyFragment2()));

    mPagerAdapter.setPagerItems(pagerItems);
    mPagerAdapter.notifyDataSetChanged();

I hope it helps.

于 2014-03-08T18:03:07.333 に答える
9

For some reason none of the answers worked for me so I had to override the restoreState method without calling super in my fragmentStatePagerAdapter. Code:

private class MyAdapter extends FragmentStatePagerAdapter {

    // [Rest of implementation]

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {}

}
于 2015-08-18T15:41:47.827 に答える
3

I slightly modified the solution provided by Bill Phillips to suit my needs

private class PagerAdapter extends FragmentStatePagerAdapter{
    Bundle oBundle;
    FragmentManager oFragmentManager;
    ArrayList<Fragment> oPooledFragments;

public PagerAdapter(FragmentManager fm) {
    super(fm);
    oFragmentManager=fm;

    }
@Override
public int getItemPosition(Object object) {

    Fragment oFragment=(Fragment)object;
    oPooledFragments=new ArrayList<>(oFragmentManager.getFragments());
    if(oPooledFragments.contains(oFragment))
        return POSITION_NONE;
    else
        return POSITION_UNCHANGED;
    } 
}

so that the getItemPosition() returns POSITION_NONE only for those fragments which are currently in the FragmentManager when getItemPosition is called. (Note that this FragmentStatePager and the ViewPager associated with it are contained in a Fragment not in a Activity)

于 2014-04-23T13:23:08.083 に答える
2

I had a similar problem but don't want to trust on the existing solutions (hard coded tag names etc.) and I couldn't make M-WaJeEh's solution work for me. Here is my solution:

I keep references to the fragments created in getItem in an array. This works fine as long as the activity is not destroyed due to configurationChange or lack of memory or whatever (--> when coming back to the activity, fragments return to their last state without 'getItem' being called again and thus without updating the array).

To avoid this problem I implemented instantiateItem(ViewGroup, int) and update my array there, like this:

        @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Object o = super.instantiateItem(container, position);
        if(o instanceof FragmentX){
            myFragments[0] = (FragmentX)o;
        }else if(o instanceof FragmentY){
            myFragments[1] = (FragmentY)o;
        }else if(o instanceof FragmentZ){
            myFragments[2] = (FragmentZ)o;
        }
        return o;
    }

So, on the one hand I'm happy that I found a solution that works for me and wanted to share it with you, but I also wanted to ask whether somebody else tried something similar and whether there is any reason why I shouldn't do it like that? So far it works very good for me...

于 2013-11-06T12:00:56.217 に答える
2

I have lived same problem and I have searched too much times. Any answer given in stackoverflow or via google was not solution for my problem. My problem was easy. I have a list, I show this list with viewpager. When I add a new element to head of the list and I refresh the viewpager nothings changed. My final solution was very easy anybody can use. When a new element added to list and want to refresh the list. Firstly set viewpager adapter to null then recreate the adapter and set i to it to viewpager.

myVPager.setAdapter(null);
myFragmentAdapter = new MyFragmentAdapter(getSupportFragmentManager(),newList);
myVPager.setAdapter(myFragmentAdapter);

Be sure your adapter must extend FragmentStatePagerAdapter

于 2017-08-07T09:10:10.727 に答える
1

I use EventBus library to update Fragment content in ViewPager. The logic is simple, just like document of EventBus how to do. It is no need to control FragmentPagerAdapter instance. The code is here:

1: Define events

Define which message which is needed to update.

public class UpdateCountEvent {
    public final int count;

    public UpdateCountEvent(int count) {
        this.count = count;
    }
}

2.Prepare subscribers

Write below code in the Fragment which is needed update.

@Override
public void onStart() {
    super.onStart();
    EventBus.getDefault().register(this);
}

@Override
public void onStop() {
    EventBus.getDefault().unregister(this);  
    super.onStop();
}

public void onEvent(UpdateCountEvent event) {//get update message
    Toast.makeText(getActivity(), event.count, Toast.LENGTH_SHORT).show();
}

3.Post events

Write below code in other Activity or other Fragment which needs to update parameter

//input update message
EventBus.getDefault().post(new UpdateCountEvent(count));
于 2015-02-13T09:38:40.637 に答える
1

I had been trying so many different approaches, none really sove my problem. Below are how I solve it with a mix of solutions provided by you all. Thanks everyone.

class PagerAdapter extends FragmentPagerAdapter {

    public boolean flag_refresh=false;

    public PagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int page) {
        FragmentsMain f;
        f=new FragmentsMain();
        f.page=page;
        return f;
    }

    @Override
    public int getCount() {
        return 4;
    }

    @Override
    public int getItemPosition(Object item) {
        int page= ((FragmentsMain)item).page;

        if (page == 0 && flag_refresh) {
            flag_refresh=false;
            return POSITION_NONE;
        } else {
            return super.getItemPosition(item);
        }
    }

    @Override
    public void destroyItem(View container, int position, Object object) {

        ((ViewPager) container).removeView((View) object);
    }
}

I only want to refresh page 0 after onResume().

 adapter=new PagerAdapter(getSupportFragmentManager());
 pager.setAdapter(adapter);

@Override
protected void onResume() {
    super.onResume();

    if (adapter!=null) {
        adapter.flag_refresh=true;
        adapter.notifyDataSetChanged();
    }
}

In my FragmentsMain, there is public integer "page", which can tell me whether it is the page I want to refresh.

public class FragmentsMain extends Fragment {

private Cursor cursor;
private static Context context;
public int page=-1;
于 2015-06-17T01:38:18.447 に答える
1

If you want to use FragmentStatePagerAdapter, please take a look at https://code.google.com/p/android/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars&groupby=&sort=&id=37990. There are issues with FragmentStatePagerAdapter that may or may not trouble your use case.

Also, link has few solutions too..few may suit to your requirement.

于 2015-08-22T21:47:22.927 に答える
1

I know am late for the Party. I've fixed the problem by calling TabLayout#setupWithViewPager(myViewPager); just after FragmentPagerAdapter#notifyDataSetChanged();

于 2015-11-12T03:35:41.170 に答える
1

This might be of help to someone - in my case when inserting a new page the view pager was asking for the position of an existing fragment twice, but not asking for the position of the new item, causing incorrect behaviour and data not displaying.

  1. Copy the source for for FragmentStatePagerAdapter (seems to have not been updated in ages).

  2. Override notifyDataSetChanged()

    @Override
    public void notifyDataSetChanged() {
        mFragments.clear();
        super.notifyDataSetChanged();
    }
    
  3. Add a sanity check to destroyItem() to prevent crashes:

    if (position < mFragments.size()) {
        mFragments.set(position, null);
    }
    
于 2016-08-23T13:34:38.600 に答える
1

Here is my implementation that incorporates the info from @Bill Phillips One gets fragment caching most of the time, except when the data has changed. Simple, and seems to work fine.

MyFragmentStatePagerAdapter.java

private boolean mIsUpdating = false;
public void setIsUpdating(boolean mIsUpdating) {
        this.mIsUpdating = mIsUpdating;
    }


@Override
public int getItemPosition(@NonNull Object object) {

    if (mIsUpdating) {
        return POSITION_NONE;
    }
    else {
        return super.getItemPosition(object);
    }
}

MyActivity.java

mAdapter.setIsUpdating(true);
mAdapter.notifyDataSetChanged();
mAdapter.setIsUpdating(false);
于 2019-01-09T17:08:24.370 に答える
1

Using ViewPager2 and FragmentStateAdapter:

Updating data dynamically is supported by ViewPager2.

There is an important note in the docs on how to get this working:

Note: The DiffUtil utility class relies on identifying items by ID. If you are using ViewPager2 to page through a mutable collection, you must also override getItemId() and containsItem(). (emphasis mine)

Based on ViewPager2 documentation and Android's Github sample project there are a few steps we need to take:

  1. Set up FragmentStateAdapter and override the following methods: getItemCount, createFragment, getItemId, and containsItem (note: FragmentStatePagerAdapter is not supported by ViewPager2)

  2. Attach adapter to ViewPager2

  3. Dispatch list updates to ViewPager2 with DiffUtil (don't need to use DiffUtil, as seen in sample project)


Example:

private val items: List<Int>
    get() = viewModel.items
private val viewPager: ViewPager2 = binding.viewPager

private val adapter = object : FragmentStateAdapter(this@Fragment) {
    override fun getItemCount() = items.size
    override fun createFragment(position: Int): Fragment = MyFragment()
    override fun getItemId(position: Int): Long = items[position].id
    override fun containsItem(itemId: Long): Boolean = items.any { it.id == itemId }
}
viewPager.adapter = adapter
    
private fun onDataChanged() {
    DiffUtil
        .calculateDiff(object : DiffUtil.Callback() {
            override fun getOldListSize(): Int = viewPager.adapter.itemCount
            override fun getNewListSize(): Int = viewModel.items.size
            override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) =
                viewPager.adapter?.getItemId(oldItemPosition) == viewModel.items[newItemPosition].id

            override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) =
                areItemsTheSame(oldItemPosition, newItemPosition)
        }, false)
        .dispatchUpdatesTo(viewPager.adapter!!)
}
于 2021-02-02T19:09:30.710 に答える
0

This solution won't work for everyone, but in my case, every Fragment in my ViewPager is a different class, and only one of them ever exist at a time.

With this constraint, this solution is safe and should be safe to use in production.

private void updateFragment(Item item) {

    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    for (Fragment fragment : fragments) {

        if (fragment instanceof MyItemFragment && fragment.isVisible()) {
            ((MyItemFragment) fragment).update(item);
        }

    }
}

If you have multiple versions of the same fragment, you can use this same strategy to call methods on those fragments to determine if it is the fragment you wish to update.

于 2016-07-06T15:31:08.180 に答える
0

I've gone through all the answers above and a number of others posts but still couldn't find something that worked for me (with different fragment types along with dynamically adding and removing tabs). FWIW following approach is what worked for me (in case anyone else has same issues).

public class MyFragmentStatePageAdapter extends FragmentStatePagerAdapter {
    private static final String TAB1_TITLE = "Tab 1";
    private static final String TAB2_TITLE = "Tab 2";
    private static final String TAB3_TITLE = "Tab 3";

    private ArrayList<String> titles = new ArrayList<>();
    private Map<Fragment, Integer> fragmentPositions = new HashMap<>();


    public MyFragmentStatePageAdapter(FragmentManager fm) {
        super(fm);
    }


    public void update(boolean showTab1, boolean showTab2, boolean showTab3) {
        titles.clear();

        if (showTab1) {
            titles.add(TAB1_TITLE);
        }
        if (showTab2) {
            titles.add(TAB2_TITLE);
        }
        if (showTab3) {
            titles.add(TAB3_TITLE);
        }
        notifyDataSetChanged();
    }


    @Override
    public int getCount() {
        return titles.size();
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = null;

        String tabName = titles.get(position);
        if (tabName.equals(TAB1_TITLE)) { 
            fragment =  Tab1Fragment.newInstance();
        } else if (tabName.equals(TAB2_TITLE)) {
            fragment =  Tab2Fragment.newInstance();
        } else if (tabName.equals(TAB3_TITLE)) {
            fragment =  Tab3Fragmen.newInstance();
        } 

        ((BaseFragment)fragment).setTitle(tabName);
        fragmentPositions.put(fragment, position);
        return fragment;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return titles.get(position);
    }

    @Override
    public int getItemPosition(Object item) {
        BaseFragment fragment = (BaseFragment)item;
        String title = fragment.getTitle();
        int position = titles.indexOf(title);

        Integer fragmentPosition = fragmentPositions.get(item);
        if (fragmentPosition != null && position == fragmentPosition) {
            return POSITION_UNCHANGED;
        } else {
            return POSITION_NONE;
        }
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);
        fragmentPositions.remove(object);
    }
}
于 2017-02-05T20:17:21.903 に答える
0

Use FragmentStatePagerAdapter instead of FragmentPagerAdapter if you want to recreate or reload fragment on index basis For example if you want to reload fragment other than FirstFragment, you can check instance and return position like this

 public int getItemPosition(Object item) {
    if(item instanceof FirstFragment){
       return 0;
    }
    return POSITION_NONE;
 }
于 2018-06-11T14:09:09.617 に答える
0

You need change instantiateItem's mFragments element getItemPosition.

    if (mFragments.size() > position) {
        Fragment f = mFragments.get(position);

        if (f != null) {
            int newPosition = getItemPosition(f);
            if (newPosition == POSITION_UNCHANGED) {
                return f;
            } else if (newPosition == POSITION_NONE) {
                mFragments.set(position, null);
            } else {
                mFragments.set(newPosition, f);
            }
        }
    }

Based AndroidX FragmentStatePagerAdapter.java, because mFragments's elements position do not change when calling notifyDataSetChanged().

Source: https://github.com/cuichanghao/infivt/blob/master/library/src/main/java/cc/cuichanghao/library/FragmentStatePagerChangeableAdapter.java

Example: https://github.com/cuichanghao/infivt/blob/master/app/src/main/java/cc/cuichanghao/infivt/MainActivityChangeablePager.kt

You can run this project to confirm how to work. https://github.com/cuichanghao/infivt

于 2020-04-09T14:19:23.163 に答える