2

我有两个使用 ViewPager 的活动,第一个使用几个 ListViews 管理 Fragments,第二个里面有 ListView 和 WebView。活动中的两个 onCreate 方法看起来都一样(唯一的区别是寻呼机类):

protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

    setContentView(R.layout.activity_subcat_list);

    mPager = new SubcatListPager(this);
    mPager.initialisePaging(false);
}

当我更改屏幕方向时会出现问题。带有 ListView 片段的 Activity 可以正常工作,但是在执行此行时,第二个 Activity 会创建带有 WebView 的片段super.onCreate(savedInstanceState);。然后在寻呼机代码中再次创建该片段。我在调试器中对其进行了跟踪,每次方向更改都会创建两个带有 webview 的片段。我通过传递 null 而不是 saved instance: 解决了这个问题super.onCreate(null);,但我认为这不是正确的方法。

有没有更好的方法来解决这个问题并恢复我在 ViewPager 中创建的片段的状态?我可以使用 savedInstanceState 并将其传递给我在寻呼机中创建的片段,但我不确定将 null 传递给活动的父项是否正确。

UPD:ManosProm 的解决方案解决了片段重新创建问题,但现在这些片段中的 getActivity 返回 null。快速搜索告诉它可能是由于片段与活动分离造成的。这是我的代码:

public CommentsPager(SherlockFragmentActivity fa, Class<? extends SherlockFragment> fragment)
    {
        mFragmentActivity = fa;
        try {
            FragmentManager fm = mFragmentActivity.getSupportFragmentManager();
            mContentFragment = (SherlockFragment) fm.findFragmentByTag(makeFragmentTag(0));
            if (mContentFragment == null)
                mContentFragment = fragment.newInstance();

            mCommentsFragment = (CommentsListFragment) fm.findFragmentByTag(makeFragmentTag(1));
            if (mCommentsFragment == null)
                mCommentsFragment = CommentsListFragment.class.newInstance();
        }
        catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(fa, "Pager creation failed: " + e.getMessage(), Toast.LENGTH_LONG).show();
        }

    }

    public void initialisePaging(boolean bInLayout) {

        //mFragmentActivity.setTitle(mFragmentActivity.getResources().getString(SiteContent.curr_cat.nameID));

        try {
            List<Fragment> fragments = new Vector<Fragment>();
            mSectionsPagerAdapter = new CommentsPagerAdapter(mFragmentActivity.getSupportFragmentManager(), fragments);

            if (!(mContentFragment instanceof ContentDownloader)) {
                throw new IllegalStateException(
                        "Fragment must implement content downloader interface.");
            }

            fragments.add(mContentFragment);
            fragments.add(mCommentsFragment);

            mViewPager = (ViewPager)mFragmentActivity.findViewById(R.id.pager);
            mViewPager.setAdapter(mSectionsPagerAdapter);

            final ActionBar actionBar = mFragmentActivity.getSupportActionBar();
            actionBar.removeAllTabs();

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

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

            //actionBar.setDisplayShowTitleEnabled(false);
            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
            actionBar.setDisplayHomeAsUpEnabled(!bInLayout);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

如何将片段重新附加到活动?或者代码很好,我应该在其他地方寻找问题?

4

1 回答 1

2

发生这种情况是因为在方向更改时,您的 viewpager 内的片段被重新创建,因此您创建了另一个相同类型的片段。但是您的第一个片段没有被破坏,它只是保留在堆栈中。所以最后你有一个面向横向的片段和一个用于纵向的片段。

将 null 传递给 onCreate 可以解决您的问题,因为没有重新创建前一个片段,但这是错误的,因为如果您使用这种方法,您可能会遇到其他问题;

要解决您的问题,您需要做的是检查片段管理器中是否已经存在该片段,然后如果它存在则返回该片段,或者如果它没有创建一个新片段并提交事务!

下面是一个示例代码(取自我的一个测试文件)。

        MFragment fragment1;
        if (fragmentManager().findFragmentByTag("android:switcher:" + R.id.viewpager + ":" + 0) == null) {
            M.LogLifecycle("Fragment1", "does not exists so instantiate");
            fragment1 = MFragment.instance("Example");

        }
        else {
            M.LogLifecycle("Fragment1", "exists so retrieve instance");
            fragment1 = (MFragment) fragmentManager().findFragmentByTag("android:switcher:" + R.id.viewpager + ":" + 0);
        }

检查"android:switcher:" + R.id.viewpager + ":" + position默认情况下 FragmentPagerAdapter 在 FragmentManager 中存储片段的方式,其中 R.id.viewpager 是布局中的视图分页器的 id,位置是视图分页器中片段的位置。

我只能给你一个例子来说明如何在 viewpager 中实现它,因为你还没有为你的项目添加太多代码。

片段的一般想法是在提交事务之前检查它们是否存在于片段管理器中,否则您可能会创建重复项。

于 2013-07-28T05:44:53.273 回答