繁体   English   中英

用新片段动态更新ViewPager

[英]Dynamically updating ViewPager with new fragments

我的应用程序中有一个简单的Pager布局,该布局应根据我的AppState进行更改。 该应用程序具有两个主要状态,即LoggedIn和LoggedOut。 如果AppState为LoggedOut,则我的标签布局应基于两个片段fragment_loginfragment_about构建。 如果应用程序状态为LoggedIn,则应基于不同的选项卡fragment_mainfragment_detailsfragment_aboutfragment_logout构建选项卡布局。

我可以使用以下两种状态之一初始化应用程序,并且一切正常。 但是,问题是用户登录后在运行时动态更改这些布局。

“选项卡”布局可以正确更改标题,但是一些旧的选项卡片段仍然存在。

设定

连接片段及其标题的我的班级

private class FragmentList {
    Class fClass;
    String fName;
    public FragmentList(Class c, String n) {
        fClass = c;
        fName = n;
    }
}

我的栏目

您可以看到我目前正在尝试将ArrayList作为参数传递,以便能够reloadtabs() ,但这仍然无法正常工作

public class SectionsPagerAdapter extends FragmentPagerAdapter {

    ArrayList<FragmentList> tabList;

    public SectionsPagerAdapter(FragmentManager fm, ArrayList<FragmentList> fragList) {
        super(fm);
        tabList = fragList;
    }

    public void reloadTabs() {
        tabList = listFragments_CurrentlyActive;
        this.notifyDataSetChanged();
    }

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

        if (position <= tabList.size()) {
            newFragmentClass = tabList.get(position).fClass;
        } else {
            newFragmentClass = tabList.get(0).fClass;
        }

        try {
            fragment = (Fragment) newFragmentClass.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //Bundle args = new Bundle();
        //args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        //fragment.setArguments(args);

        return fragment;
    }

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

    @Override
    public CharSequence getPageTitle(int position) {
        if (position <= tabList.size()) {
            return tabList.get(position).fName;
        } else {
            return "Unknown";
        }
    }
}

初始化片段列表

注意:每个片段都有自己的FRAGMENTNAME公用静态字符串

private ArrayList<FragmentList> listFragmentsLoggedOut = new ArrayList<>();
private ArrayList<FragmentList> listFragmentsLoggedIn = new ArrayList<>();

listFragmentsLoggedOut.add(new FragmentList(fragment_login.class, fragment_login.FRAGMENT_NAME));
listFragmentsLoggedOut.add(new FragmentList(fragment_about.class, fragment_about.FRAGMENT_NAME));

listFragmentsLoggedIn.add(new FragmentList(fragment_main.class, fragment_main.FRAGMENT_NAME));
listFragmentsLoggedIn.add(new FragmentList(fragment_details.class, fragment_details.FRAGMENT_NAME));
listFragmentsLoggedIn.add(new FragmentList(fragment_about.class, fragment_about.FRAGMENT_NAME));
listFragmentsLoggedIn.add(new FragmentList(fragment_logout.class, fragment_logout.FRAGMENT_NAME));

建立TabLayouts

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    initApp();

    refreshTabsBasedOnNewState();
}

 //Separate method that can be called from elsewhere to update the Tabs
 public void refreshTabsBasedOnNewState() {


    //Can swap these and the app displays and functions correctly.
    listFragments_CurrentlyActive = listFragments_LoggedOut;
    //listFragments_CurrentlyActive = listFragments_LoggedIn;

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager(), listFragments_CurrentlyActive);

    //update adapter class
    mSectionsPagerAdapter.reloadTabs();

    sectionsAdapterACTIVE.notifyDataSetChanged();

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.container);
    mViewPager.setAdapter(sectionsAdapterACTIVE);


    TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(mViewPager);

}

当前输出

当应用程序被硬编码为LoggedIn ,两个片段和选项卡将正确显示。 与将应用程序硬编码为LoggedOut 但是,当我尝试更改布局时,通过更改listFragments_CurrentlyActive的值, listFragments_CurrentlyActive得到以下行为:

  • 标签页从2增加到4,并具有正确的标题(和顺序)
  • 关联的片段是原始片段中的2个,新片段中的2个。

实际上,选项卡是正确的,但是显示的片段是以下fragment_login fragment_aboutfragment_loginfragment_aboutfragment_aboutfragment_logout

因此,您可以看到正确添加了另外两个片段,但是两个初始片段仍引用LoggedOut片段。

可能有一个非常简单的解决方案,其中我需要使用mSectionsPagerAdapter.notifyDataSetChanged()来更新适配器或重建它,但是我在任何地方都找不到修复程序。 非常感谢。 Ĵ

编辑

我什至尝试在一开始就创建适配器,所以它们是完全独立的,但是仍然会发生相同的行为

SectionsPagerAdapter sectionsAdapter_LoggedOut = new SectionsPagerAdapter(getSupportFragmentManager(), listFragmentsLoggedOut);
SectionsPagerAdapter sectionsAdapter_LoggedIn = new SectionsPagerAdapter(getSupportFragmentManager(), listFragmentsLoggedIn);

SectionsPagerAdapter sectionsAdapterACTIVE;

sectionsAdapterACTIVE = (AppState.isLoggedIn) ? sectionsAdapter_LoggedIn : sectionsAdapter_LoggedOut

使用getSupportFragmentManager()的片段缓存可能会出现问题吗?

编辑2

添加了此图像以帮助可视化问题。 不知道我是否事先足够清楚。

缓存片段的状态更改问题

解决了

问题在另一个线程上由以下答案描述

如果要切换出正在显示的实际片段,则需要避免FragmentPagerAdapter并使用FragmentStatePagerAdapter

FragmentPagerAdapter无法工作,因为它在第一次显示后就不会销毁片段,因此我遇到了缓存问题。 但是,我没有重写getItemPosition(Object item) ,就像建议的答案一样。 当我更换时,我的问题就消失了:

public class SectionsPagerAdapter extends FragmentPagerAdapter {

public class SectionsPagerAdapter extends FragmentStatePagerAdapter {

暂无
暂无

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

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