Android 每次更改方向后都重新创建碎片,无法恢复状态

Android 每次更改方向后都重新创建碎片,无法恢复状态,android,android-fragments,android-configchanges,Android,Android Fragments,Android Configchanges,更新:事实证明问题来自其他地方。感谢@Luksprog指出我忽略的东西 该项目是使用Android Studio的导航抽屉模式创建的。抽屉在NavigationDrawerFragment类中实现 当选择抽屉中的特定项目时,会添加保存视图寻呼机的片段。代码是在我的家庭活动中实现的 当屏幕旋转时,将调用NavigationDrawerFragment的onCreate() 这里是出错的地方-在重新创建时,NavigationDrawerFragment将再次调用selectItem(),这将触发我

更新:事实证明问题来自其他地方。感谢@Luksprog指出我忽略的东西

  • 该项目是使用Android Studio的导航抽屉模式创建的。抽屉在
    NavigationDrawerFragment
    类中实现
  • 当选择抽屉中的特定项目时,会添加保存视图寻呼机的片段。代码是在我的家庭活动中实现的
  • 当屏幕旋转时,将调用
    NavigationDrawerFragment
    onCreate()
  • 这里是出错的地方-在重新创建时,
    NavigationDrawerFragment
    将再次调用selectItem(),这将触发我的菜单项selected处理程序。这会导致Android还原ListFragment
  • 这可以通过检查“我的菜单选择”处理程序代码中的活动菜单项来防止


    无论出于何种原因(例如方向更改)重新创建活动时,我希望保留
    ViewPager
    的最后一个查看页面索引

    ViewPager
    位于一个
    Fragment
    (名为
    ListFragment
    )中,该片段附加到活动。我使用的是compat库,因此片段是android.support.v4.app.fragment
    的子类

    我认为可以通过重写
    onSaveInstanceState()
    方法并在
    onCreate()
    中添加适当的逻辑来实现,如下所述:

    要正确处理重新启动,您的活动 在正常的活动生命周期中恢复其以前的状态 哪一个Android在破坏您的应用程序之前调用onSaveInstanceState() 活动,以便保存有关应用程序状态的数据。你 然后可以在onCreate()或 onRestoreInstanceState()

    但碎片的情况似乎有所不同。当我从这个
    ListFragment
    导航到另一个活动并按下“后退”键时,页面索引可以正确恢复。但是,当我旋转设备时,页面索引将丢失

    我添加了一些日志以查看问题所在。从日志中,我发现尽管正确调用了
    ListFragment
    (我将其称为ListFragment A)的
    onSaveInstanceState()
    ,但该特定片段类不再显示在活动中。当方向改变并且重新创建活动时,Android会调用
    onSaveInstanceState()
    ,然后调用
    onDetach()
    ,以分离此片段。然后,Android创建一个新的
    ListFragment
    (我称之为ListFragment B)实例,并将其附加到新的旋转活动。此ListFragment B向构造函数传递了一个空的
    savedInstanceState
    ,因此最后一页索引(以及片段A的savedInstanceState中的任何配置)将丢失

    事实上,每次屏幕旋转时,都会创建一个新的
    ListFragment
    实例,但旧实例似乎不会被销毁。旋转设备时,我会看到如下日志:

    D/ListFragment﹕ [1110257048] onSaveInstanceState() called, storing last page index 3
    D/ListFragment﹕ [1109835992] onSaveInstanceState() called, storing last page index 0
    D/ListFragment﹕ [1108826176] onSaveInstanceState() called, storing last page index 0
    D/ListFragment﹕ [1108083096] onSaveInstanceState() called, storing last page index 0
    D/ListFragment﹕ [1106541040] onSaveInstanceState() called, storing last page index 0
    D/ListFragment﹕ [1108316656] onSaveInstanceState() called, storing last page index 0
    D/ListFragment﹕ [1109134136] onSaveInstanceState() called, storing last page index 0
    D/ListFragment﹕ [1108630992] onSaveInstanceState() called, storing last page index 0
    D/ListFragment﹕ [1108592888] onSaveInstanceState() called, storing last page index 0
    D/ListFragment﹕ [1109729064] onSaveInstanceState() called, storing last page index 0
    D/ListFragment﹕ [1110257048] onDestroy()
    D/ListFragment﹕ [1110257048] onDetach()
    D/ListFragment﹕ [1109835992] onDestroy()
    D/ListFragment﹕ [1109835992] onDetach()
    D/ListFragment﹕ [1108826176] onDestroy()
    D/ListFragment﹕ [1108826176] onDetach()
    D/ListFragment﹕ [1108083096] onDestroy()
    D/ListFragment﹕ [1108083096] onDetach()
    D/ListFragment﹕ [1106541040] onDestroy()
    D/ListFragment﹕ [1106541040] onDetach()
    D/ListFragment﹕ [1108316656] onDestroy()
    D/ListFragment﹕ [1108316656] onDetach()
    D/ListFragment﹕ [1109134136] onDestroy()
    D/ListFragment﹕ [1109134136] onDetach()
    D/ListFragment﹕ [1108630992] onDestroy()
    D/ListFragment﹕ [1108630992] onDetach()
    D/ListFragment﹕ [1108592888] onDestroy()
    D/ListFragment﹕ [1108592888] onDetach()
    D/ListFragment﹕ [1109729064] onDestroy()
    D/ListFragment﹕ [1109729064] onDetach()
    D/ListFragment﹕ [1110903656] onAttach()
    D/ListFragment﹕ [1110903656] onCreate()
    D/ListFragment﹕ [1110903656] savedInstanceState is not NULL.
    D/ListFragment﹕ [1110903656] Retrieving last page index 3
    D/ListFragment﹕ [1110905248] onAttach()
    D/ListFragment﹕ [1110905248] onCreate()
    D/ListFragment﹕ [1110905248]   savedInstanceState is not NULL.
    D/ListFragment﹕ [1110905248]   Retrieving last page index 0
    D/ListFragment﹕ [1110906440] onAttach()
    D/ListFragment﹕ [1110906440] onCreate()
    D/ListFragment﹕ [1110906440]   savedInstanceState is not NULL.
    D/ListFragment﹕ [1110906440]   Retrieving last page index 0
    D/ListFragment﹕ [1110907632] onAttach()
    D/ListFragment﹕ [1110907632] onCreate()
    D/ListFragment﹕ [1110907632]   savedInstanceState is not NULL.
    D/ListFragment﹕ [1110907632]   Retrieving last page index 0
    D/ListFragment﹕ [1110908824] onAttach()
    D/ListFragment﹕ [1110908824] onCreate()
    D/ListFragment﹕ [1110908824]   savedInstanceState is not NULL.
    D/ListFragment﹕ [1110908824]   Retrieving last page index 0
    D/ListFragment﹕ [1110910016] onAttach()
    D/ListFragment﹕ [1110910016] onCreate()
    D/ListFragment﹕ [1110910016]   savedInstanceState is not NULL.
    D/ListFragment﹕ [1110910016]   Retrieving last page index 0
    D/ListFragment﹕ [1110911208] onAttach()
    D/ListFragment﹕ [1110911208] onCreate()
    D/ListFragment﹕ [1110911208]   savedInstanceState is not NULL.
    D/ListFragment﹕ [1110911208]   Retrieving last page index 0
    D/ListFragment﹕ [1110912400] onAttach()
    D/ListFragment﹕ [1110912400] onCreate()
    D/ListFragment﹕ [1110912400]   savedInstanceState is not NULL.
    D/ListFragment﹕ [1110912400]   Retrieving last page index 0
    D/ListFragment﹕ [1110913592] onAttach()
    D/ListFragment﹕ [1110913592] onCreate()
    D/ListFragment﹕ [1110913592]   savedInstanceState is not NULL.
    D/ListFragment﹕ [1110913592]   Retrieving last page index 0
    D/ListFragment﹕ [1110914784] onAttach()
    D/ListFragment﹕ [1110914784] onCreate()
    D/ListFragment﹕ [1110914784]   savedInstanceState is not NULL.
    D/ListFragment﹕ [1110914784]   Retrieving last page index 0
    D/HomeActivity﹕ fragment updated
    D/ListFragment﹕ [1110914784] onCreateView()
    D/ListFragment﹕ [1111031048] onAttach()
    D/HomeActivity﹕ Fragment attached.
    D/ListFragment﹕ [1111031048] onCreate()
    D/ListFragment﹕ [1111031048]   savedInstanceState is NULL.
    D/ListFragment﹕ [1111031048] onCreateView()
    D/ListFragment﹕ [1111031048] onResume(), restoring page index 0
    
    这是我旋转屏幕大约10次后的日志。标记中的数字是类“
    hashCode()
    。以上几行显示,先前创建的片段的
    onSaveInstanceState()
    onCreate()
    即使被最新的片段(1111031048)替换,仍然会被调用

    注意,我没有在fragment类中调用
    setRetainInstance()
    。事实上,我尝试了
    setRetainInstance(false)
    setRetainInstance(true)
    ,但没有改变任何事情

    我做错什么了吗?我可以理解需要重新创建
    ListFragment
    ,但为什么
    savedInstanceState
    为空?如果这是预期的行为,那么解决我的需求的正确方法是什么,即在配置更改时保持页面索引


    应该可以将页面索引设置为静态类变量,但我不确定它是否真的解决了问题,或者只是隐藏了它(因为我在上面的日志中发现内存泄漏)

    尝试在此处使用
    onCreateView()
    而不是
    onCreate()
    ,这是特定于片段的,可能会有所不同

    重写
    onSaveInstanceState()
    以存储您的状态,并使用
    savedInstanceState.get*()
    onCreateView()中恢复它。我们在应用程序中就是这样做的,而且应该是这样。正如@Ari提到的,确保调用
    super.onSaveInstanceState(outState)


    如问题中所述,这一问题已得到解决,再次感谢@Luksprog指出了我忽略的内容

    片段
    的行为实际上与
    活动
    类一致

    以下是我的问题的原因:

    • 该项目是使用Android Studio的“创建项目”向导提供的导航抽屉模式创建的。抽屉在
      NavigationDrawerFragment
      类中实现
    • 当选择抽屉中的特定项目时,会添加保存视图寻呼机的片段。代码是在我的家庭活动中实现的
    • 当屏幕旋转时,将调用
      NavigationDrawerFragment
      onCreate()
    • 这里是问题所在-在重新创建时,
      NavigationDrawerFragment
      将再次调用
      selectItem()
      ,这将触发我的菜单项selected处理程序。这将导致替换
      ListFragment

    通过在“我的菜单选择处理程序代码”中检查活动菜单项,或禁用该
    selectItem()
    调用,可以防止出现这种情况

    尽管答案已经被接受,但让我进一步澄清一下:“问题”在Android Studio模板中。正如Edmund指出的,问题在于导航抽屉中调用
    class MyFragment extends ListFragment {
    
        @Override
        public void onSaveInstanceState(Bundle outState) {
            outState.putString(ARG_PAGE, page); 
            super.onSaveInstanceState(outState);
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            if(savedInstanceState != null){
                if(savedInstanceState.containsKey(ARG_PAGE)){
                    page = savedInstanceState.getInteger(ARG_PAGE);
                }
            }
        }
    }
    
        @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        // Read in the flag indicating whether or not the user has demonstrated awareness of the
        // drawer. See PREF_USER_LEARNED_DRAWER for details.
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
        mUserLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false);
    
        if (savedInstanceState != null) {
            mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
            mFromSavedInstanceState = true;
        }
    
        // Select either the default item (0) or the last selected item.
        selectItem(mCurrentSelectedPosition);
    
    }
    
        @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        // Read in the flag indicating whether or not the user has demonstrated awareness of the
        // drawer. See PREF_USER_LEARNED_DRAWER for details.
        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
        mUserLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false);
    
        if (savedInstanceState != null) {
            mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
            mFromSavedInstanceState = true;
        } else {
            // Select either the default item (0) or the last selected item.
            selectItem(mCurrentSelectedPosition);
        }
    }
    
    <activity android:name=".MainActivity"
    android:configChanges="orientation|screenSize">
    </activity>
    
    private void openFragment(Fragment fragment, String tag) {
                FragmentManager fragmentManager = getSupportFragmentManager();
                FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
                Fragment existingFragment = fragmentManager.findFragmentByTag(tag);
                if (existingFragment != null) {
                    fragmentTransaction.add(R.id.container, fragment, tag);
                    fragmentTransaction.commit();
                }
            }