繁体   English   中英

Android-使用FragmentStatePageAdapter保存/恢复状态

[英]Android - Save/restore state with FragmentStatePageAdapter

我参加了这堂课:

public class My_ViewPagerAdapter extends FragmentStatePagerAdapter {

    private ArrayList<My_Fragment> fragments=new ArrayList<>();
    private ArrayList<String> tabTitles=new ArrayList<>();

    public My_ViewPagerAdapter(FragmentManager fm) {

        super(fm);
    }

    @Override
    public Fragment getItem(int position) {

        return fragments.get(position);
    }

    @Override
    public int getItemPosition(Object object) {

        for (int i=0;i<fragments.size();i++){

            Class<? extends My_Fragment> clazz= fragments.get(i).getClass();

            if (clazz.isInstance(object)){

                return i;
            }
        }
        return POSITION_NONE;
    }

    @Override
    public int getCount() {

        return fragments.size();
    }

    public void addFragment(My_Fragment fragment, String tabTitle){

        fragments.add(fragment);
        tabTitles.add(tabTitle);
        notifyDataSetChanged();
    }

    public void removeFragment(int position){

        fragments.remove(position);
        tabTitles.remove(position);
        notifyDataSetChanged();
    }

    public My_Fragment getFragmentAtTab(int position){

        return fragments.get(position);
    }

    @Override
    public CharSequence getPageTitle(int position) {

        return tabTitles.get(position);
    }
}

我正在动态添加/删除片段/选项卡,并且我想通过配置更改来保存它们的状态。

我实现了onSaveInstanceState():

int tabs=tabLayout.getTabCount();

    for (int i=0;i<tabs;i++){

        outState.putInt("TabsCount",tabs);
        outState.putString("Tab_"+i,getTabTitle(i));
        outState.putString("FragmentClassAtTab_"+i,my_viewPagerAdapter.getFragmentAtTab(i).getClass().getName());
    }

我实现了onRestoreInstanceState():

for (int i=0;i<tabs;i++){

        try {

            My_Fragment fragment= (My_Fragment) Class.forName(savedInstanceState.getString("FragmentClassAtTab_"+i)).newInstance();
            addTab(fragment ,savedInstanceState.getString("Tab_"+i));
        }
        catch (ClassNotFoundException e) {

            e.printStackTrace();
        }
        catch (InstantiationException e) {

            e.printStackTrace();
        }
        catch (IllegalAccessException e) {

            e.printStackTrace();
        }
    }

addTab方法是:

public void addTab(My_Fragment fragment, String title){

    if (fragment!=null) my_viewPagerAdapter.addFragment(fragment,title);
    tabLayout.addTab(tabLayout.newTab().setText(title));
}

问题:

配置更改发生时,我添加的每个片段都会“自动”重新创建,因此每次都调用其构造函数。 onCreateView在这些实例上调用,而不是在我的代码重新创建的实例上调用

我需要onCreateView才能调用我的选项卡中实例化的片段,以便设置其列表视图。

通过我的onRestoreInstanceState方法“自动”创建的片段被新的片段实例替换,但是在这些新实例上没有调用onCreateView方法。

我认为我做错了,也许有一种更好的方法可以通过更改配置来保存选项卡和片段...任何帮助,不胜感激。

我曾经创建过类似的东西,在我的情况下看起来像这样:

public class DisplayPagerAdapter extends FragmentStatePagerAdapter  {

    private static final String TAG = "DisplayPagerAdapter";

    SparseArray<DisplayFragment> registeredFragments = new SparseArray<DisplayFragment>();

    private final Context context;
    private final DisplayCoreModule display;
    private final FragmentManager fm;

    private boolean isAddOrRemoving;

    public DisplayPagerAdapter(Context context, FragmentManager fm,
            DisplayCoreModule display) {
        super(fm);
        this.context = context;
        this.display = display;
        this.fm = fm;

        Log.d(TAG, "pages " + display.getPagesCount());
    }


    public void notifySizeChangingDataSetChange() {
        isAddOrRemoving = true;
        notifyDataSetChanged();
        isAddOrRemoving = false;
    }

    @Override
    public int getCount() {
        int count = (display != null && display.getPagesCount() > 0) ? display
                .getPagesCount() : 1;
        return count;
    }

    @Override
    public int getItemPosition(Object object) {
        DisplayFragment frag = (DisplayFragment) object;
        if (!display.containsPageId(frag.getPageId())) {
            // this will update the 'no information' page with id -1
            return POSITION_NONE;
        }
        if (isAddOrRemoving) {
            // recreate all for simplicity
            return POSITION_NONE;
        }
        return POSITION_UNCHANGED;
    }

    @Override
    public Fragment getItem(int position) {
        Log.d(TAG, "getItem " + position);
        return DisplayFragment.newInstance(position);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        if (display != null && display.getPagesCount() > 0) {
            return context.getString(R.string.page) + " " + (position + 1);
        } else {
            return super.getPageTitle(position);
        }
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Log.d(TAG, "instantiateItem " + position);
        DisplayFragment fragment = (DisplayFragment) super.instantiateItem(
                container, position);
        registeredFragments.put(position, fragment);
        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        Log.d(TAG, "destroyItem " + position);
        registeredFragments.remove(position);
        super.destroyItem(container, position, object);
    }

    public Fragment getRegisteredFragment(int position) {
        return registeredFragments.get(position);
    }

    public SparseArray<DisplayFragment> getRegisteredFragments() {
        return registeredFragments;
    }

}

自从我写这篇文章以来已经有很长时间了,因此无法详细介绍。

但是,需要注意的关键一点(我想)是我有一个外部“簿记员”(DisplayCoreModule)。 每当DisplayCoreModule中的片段数量发生变化时,我只需调用notifySizeChangingDataSetChange()来使FragmentStatePagerAdapter刷新内容。

考虑到您的一些问题, FragmentStatePagerAdapter不会在显示片段之前调用片段的onCreateView 通常,这仅意味着三个片段:您当前正在查看的片段以及该片段两侧的一个片段。

也许想一想,问题的根源在于缺少带有POSITION_NONE的getItemPosition() 似乎在回忆起更新动态内容的必要性。 使notifyDataSetChanged具有适当的作用。

棘手的解决方案:

我只是修改了我的addTab方法:

public void addTab(My_Fragment fragment, String title){

    boolean createFragment=true;

    if (getTabCount()>0){
        //all tabs must have different names
        for (int i=0;i<getTabCount();i++){

            if (getTabTitle(i).equals(title)==true){

                createFragment=false;
                break;
            }
        }
    }

    if (createFragment && fragment!=null){
        //this ensures that if a fragment of the same type already exists, that should be the one to be added, tabs are made of fragments of different classes, so there will be no problem while checking this.
        for (Fragment f: my_activity.getSupportFragmentManager().getFragments()){

            if (fragment.getClass().isInstance(f)){

                my_viewPagerAdapter.addFragment((My_Fragment)f,title);
                tabLayout.addTab(tabLayout.newTab().setText(title));
                return;
            }
        }
        my_viewPagerAdapter.addFragment(fragment,title);
        tabLayout.addTab(tabLayout.newTab().setText(title));
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM