保留ViewPager中Fragments的状态(Android)

5
我在一个fragment中有一个viewpager,其中我展示了3个fragment,但是当我第一次打开该fragment时,它能正常打开,但当我切换到另一个fragment并回到viewpager fragment时,它就不显示viewpager中的fragment了。此时,我必须要么改变手机的方向,要么不断滑动viewpager才能显示隐藏的fragment。
我已经查找过谷歌,现在我知道我需要为每个fragment设置标签,并使用findfragmentbytag方法检索fragment,但问题是当我尝试将标签设置为fragment时。
getSupportFragmentManager().beginTransaction().add(myFragment, "Some Tag").commit();

上面这行代码导致了我的应用程序崩溃,logcat显示“无法将标签设置为片段”,我知道我犯了一些愚蠢的错误。

这是我的片段完整代码。如果有人能指导我在哪里编写设置片段标记的代码,我将不胜感激。提前致谢。

public class MatchesListingFragment extends Fragment implements ActionBar.TabListener {

    Context context;
    SectionsPagerAdapter mSectionsPagerAdapter;
    ViewPager mViewPager;
    ActionBar actionBar;
    Matchlistings db;
    Bundle savedInstanceState;

    Fragment livescore,fixture,results;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        this.savedInstanceState = savedInstanceState;
        db = new Matchlistings(getActivity());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_matches, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        context = getActivity().getApplicationContext();

        if(savedInstanceState == null){
            livescore = new LiveScoreListingFragment();
            fixture = new FixturesListingFragment();
            results = new ResultsListingFragment();
        }

        if(!Constants.is_listing_refreshed){
            Log.i(MainActivity.TAG,"refreshing list");
            db.loadListingsFromServer().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        }

        actionBar = getActivity().getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        if(mSectionsPagerAdapter == null)
        mSectionsPagerAdapter = new SectionsPagerAdapter(getActivity().getSupportFragmentManager());
        mViewPager = (ViewPager) getView().findViewById(R.id.pager);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                actionBar.setSelectedNavigationItem(position);
            }
        });


        for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
            Tab tb = actionBar.newTab()
            .setText(mSectionsPagerAdapter.getPageTitle(i))
            .setTabListener(this);

            actionBar.addTab(tb);

        }
    }

    public class SectionsPagerAdapter extends FragmentPagerAdapter {
        Fragment fragment;

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

        @Override
        public Fragment getItem(int position) {
            switch(position){
            case 0:

                fragment = livescore;
                return fragment;
            case 1:
                fragment = fixture;
                return fragment;
            case 2:
                fragment = results;
                return fragment;
            case 3:
                fragment = new LiveScoreListingFragment();
                return fragment;
            }
            return null;
        }

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

        @Override
        public CharSequence getPageTitle(int position) {
            switch (position) {
            case 0:
                return "LIVE";
            case 1:
                return "FIXTURES";
            case 2:
                return "RESULTS";
            case 3:
                return "HOT";
            }
            return null;
        }
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        actionBar.removeAllTabs();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
    }

    @Override
    public void onTabReselected(Tab arg0, FragmentTransaction arg1) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onTabSelected(Tab arg0, FragmentTransaction arg1) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onTabUnselected(Tab arg0, FragmentTransaction arg1) {
        // TODO Auto-generated method stub

    }

}

输入图像描述

编辑: 我现在尝试通过标签从viewpager获取片段,而不是每次创建新的片段。但问题仍然存在。

FixturesListingFragment fixture = (FixturesListingFragment) getActivity().getSupportFragmentManager().findFragmentByTag("android:switcher:"+R.id.pager+":1");
                if(fixture == null)
                    fixture = new FixturesListingFragment();

FragmentPagerAdapter 使用标签本身。 - MGDroid
我该如何使用它来获取片段? - Wasif Khalil
4个回答

12

你尝试使用setOffscreenPageLimit了吗?如果你有3个页面,则将其设置为2。这样,即使应用程序处于闲置状态,页面也不会被重新创建。这是链接


在设置适配器后,页面数量为4,您应该将其离屏页面限制设置为3。 - Angmar
但是为什么需要“获取”这些片段呢?如果片段创建存在问题,您应该检查布局是否设计正确。如果您正在尝试使用滑动手势实现操作栏选项卡,则应遵循此链接:http://developer.android.com/training/implementing-navigation/lateral.html - Angmar
1
嘿@angmar,谢谢兄弟,我通过将FragmentPagerAdapter更改为FragmentStatePagerAdapter来解决了它...简直不敢相信这是一个如此小的问题... :D 谢谢兄弟! - Wasif Khalil
1
这就是解决我的问题的方法.../ ** * {@link android.support.v4.view.PagerAdapter} 将提供应用程序的三个主要部分的片段。我们使用 * {@link android.support.v4.app.FragmentPagerAdapter} 衍生类,它会将每个已加载的片段保持在内存中。如果这变得过于占用内存, * 最好切换到 {@link android.support.v4.app.FragmentStatePagerAdapter}。 */ - Wasif Khalil
太好了,很棒你能解决这个问题。我没有注意到你使用的是FragmentPagerAdapter而不是FragmentStatePagerAdapter,但在这种情况下确实更好的选择。 - Angmar
显示剩余3条评论

5
我已经通过使用setOffScreenpageLimit(int)将额外选项卡的数量设置为解决此问题。
private void setupViewPager(ViewPager viewPager) {
    ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
    adapter.addFragment(new FragmentHome(), "Home");
    adapter.addFragment(new FragmentEProfile(), "e-Profile");
    adapter.addFragment(new FragmentResults(), "Results");
    adapter.addFragment(new FragmentOutpass(), "Outpass");
    viewPager.setAdapter(adapter);
    viewPager.setOffscreenPageLimit(3);
}

4
我已经通过将FragmentPagerAdapter更改为FragmentStatePagerAdapter来解决了问题... 这是我从链接下载的示例应用程序中读到的内容。
/**
     * The {@link android.support.v4.view.PagerAdapter} that will provide fragments for each of the
     * three primary sections of the app. We use a {@link android.support.v4.app.FragmentPagerAdapter}
     * derivative, which will keep every loaded fragment in memory. If this becomes too memory
     * intensive, it may be best to switch to a {@link android.support.v4.app.FragmentStatePagerAdapter}.
     */

我已经修改了它,但仍然想知道是否有一种使用FragmentPagerAdapter的方法可以实现。


0

尝试按照以下方式保留实例:

 @Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    //add this line
    setRetainInstance(true);

    context = getActivity().getApplicationContext();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接