如何在重新创建活动时(例如在轮换时)跟踪ViewPager的选定片段

时间:2014-08-21 07:18:37

标签: android android-fragments android-viewpager

我的Android 4+应用的MainActivity使用ViewPager在5个不同的片段之间切换。活动和片段都必须知道当前选择/显示哪个片段。 MainActivity使用ViewPagers OnPageChangeListener跟踪此信息。 MainActivity还保留对FragmentPagerAdapter创建的片段的引用,以便在选择片段时能够通知片段。

问题是,MainActivty(当然)在重新创建片段时会丢失对片段的引用,例如:旋转设备时。如果重新创建的MainActivity会重新获取FragmentPagerAdapter中的信息,这不会是一个大问题,但事实并非如此。

似乎ViewPager会在调用super.onCreate(savedInstanceState)时自动重新创建Framgent,而不会询问FragmentPagerAdapter这是一个问题,因为这样MainActivty没有获得有关创建的片段的任何信息,也无法保存对它的引用。

如何解决这个问题?

// MainActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
    // When the activity is re-creates, e.g. on rotation, the viewPager
    // Fragments are created here without knowledge of the MainActivity. 
    super.onCreate(savedInstanceState);
    ...

    ViewPager viewPager = (ViewPager)findViewById(R.id.pager);
    viewPager.setAdapter(new SectionsPagerAdapter(getSupportFragmentManager()));

    currentPageIndex = -1;
    viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            updateCurrentPageIndex(position);
        }
    });

    @Override
    protected void onResume () {                
       super.onResume();
       updateCurrentPageIndex(currentPageIndex);
    }


    private void updateCurrentPageIndex(int index) {
        currentPageIndex = position;

        if (pageOneFragment != null && position == 0)
            pageOneFragment.onSelectedInViewPager();

        if (pageTwoFragment != null && position == 0)
            pageTwoFragment.onSelectedInViewPager();

        ...
    }


    Fragment pageOnFragment;
    Fragment pageTwoFragment;
    ...

    private class SectionsPagerAdapter extends FragmentPagerAdapter {
        ...

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

           if (position == 0) {
               pageOneFragment = PageOneFragmet.newInstance();
               fragment = pageOneFragment;
           }                          

           if (position == 1) {
               pageTwoFragment= PageTwoFragmet.newInstance();
               fragment = pageTwoFragment;
           } 

           ...

           return fragment;
        }
    }
}

编辑:感谢您的回答,但(我认为)保存实例状态并不能解决问题。当然我知道将Date保存到实例状态的可能性。因此,获取有关当前索引的信息不是一个大问题。问题是,MainActivity无法通知所选的Fragment,因为它没有引用它。片段不是在适配器中创建的,而是由ViewPager自动创建的。因此,活动不会获得有关片段的任何信息,也无法通知它有关活动的信息......

3 个答案:

答案 0 :(得分:2)

创建界面

public interface FragmentListener {
    void onFragmentActivated(Fragment f);
}

在您的活动中实施此界面。然后在你的片段中:

@Override 
public void onResume() {
    super.onResume();
    ((FragmentListener)getActivity()).onFragmentActivated(this);
}

现在,当您在活动中调用此回调时,您知道哪个片段已激活

答案 1 :(得分:0)

在onSaveInstanceState()中,您应该“放置”您想要跟踪的任何内容。在onCreate()中,您可以“获取”这些项目。

private static final String KEY_BUNDLE_CURRENT_PAGE_STATE = "current_page_state";

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt(KEY_BUNDLE_CURRENT_PAGE_STATE, currentPageIndex);
}

@Override
public void onCreate(Bundle savedInstanceState){
    // ...
    if (savedInstanceState != null && savedInstanceState.containsKey(KEY_BUNDLE_CURRENT_PAGE_STATE) {
        currentPageIndex = savedInstanceState.getInt(KEY_BUNDLE_CURRENT_PAGE_STATE);
    }
    // ...
}

答案 2 :(得分:0)

试试这个

private static final String INDEX = "f_index";
private int mCurrentIndex ; // the current index will be updated thru position
// orientation change occurs
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current index state
    savedInstanceState.putInt(INDEX, mCurrentIndex);

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

...
// this is where we get the data back if we are recreated
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // Always call the superclass first

    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        // Restore value of members from saved state
        mCurrentIndex= savedInstanceState.getInt(INDEX);
    } else {
        // Probably initialize members with default values for a new instance
    }
    ...
}

A nice lifecycle here 这里有一个很好的生命周期图。

修改

希望它有所帮助:)