屏幕旋转后2片段,保存值丢失

时间:2013-11-17 18:54:35

标签: android android-fragments rotation savestate

基于来自示例API的FragmentLayout示例,我遇到了片段问题 如下所述:http://developer.android.com/guide/components/fragments.html#Example

除非我想在Bundle of DetailsFragment中保存/恢复值,否则一切正常 处理屏幕旋转。

为了说明这一点,我修改了FragmentLayout示例的DetailsFragment 附加一个随机值 (在TextView底部模拟对片段的操作) 并且此值保存在onSaveInstanceState中并在onCreateView中检索。

现在问题是:

  1. 以纵向模式开始并选择列表中的项目 DetailsFragment显示为 新的意图在底部有一个随机值。
  2. 以横向模式旋转设备 该列表位于左侧,包含所选项目 突出显示(我移动了getListView()的调用.setItemChecked(mCurCheckPosition,true) 在TitlesFragment的onStart方法中因为它不起作用 当在showDetail方法中制作时)在右侧, 显示DetailsFragment 文本对应于所选项目但值 不是那个得救的人 但是新的 如log(见下文)所示,在旋转之后创建DetailsFragment并且随机值为 正确恢复但TitleFragment创建了另一个实例,因为 findFragmentById返回null,DetailsFragment创建一个新的随机值 所以有 两个片段,一个可见,具有错误的随机值,另一个在某处,不可见, 我需要的价值!

    如何解决此问题以显示正确的片段,当然不创建新片段?

    如果我们继续旋转设备:
  3. 以纵向模式向后旋转,然后再次选择与第1点相同的项目
  4. 以横向模式再次旋转 现在findFragmentById返回一个片段并作为 getShownIndex获取与索引相同的值,没有DetailsFragment的新实例,显示第2点显示的randon值
  5. 这是带注释的日志

    ********************************************************
    * 1. Start in portrait mode - select item 6 (Othello)  *
    * new DetailsFragment created with new rand value 4769 *
    * this value is saved in onSaveInstanceState           *
    ********************************************************
    
    D/TitlesFragment(21894): Entering onCreateView
    D/TitlesFragment(21894): Entering onActivityCreated
    D/TitlesFragment(21894): onActivityCreated - portrait mode
    D/TitlesFragment(21894): Entering onStart
    D/TitlesFragment(21894): Entering showDetails - index: 6
    D/TitlesFragment(21894): showDetails - Single Pane - start new activity
    D/TitlesFragment(21894): showDetails - position: 6 - title: Othello
    
    D/DetailsActivity(21894): Entering onCreate
    D/DetailsActivity(21894): onCreate - portrait mode
    D/DetailsActivity(21894): onCreate - new DetailsFragment: DetailsFragment{41980540}
    
    D/DetailsFragment(21894): Entering onCreateView - this: DetailsFragment{41980540 #0 id=0x1020002}
    D/DetailsFragment(21894): onCreateView - new mRandValue: 4769
    
    D/TitlesFragment(21894): Entering onSaveInstanceState - save position: 6
    
    D/DetailsFragment(21894): Entering onSaveInstanceState - this: DetailsFragment{41980540 #0 id=0x1020002}
    D/DetailsFragment(21894): onSaveInstanceState - save value: 4769
    
    
    *********************************************************
    * 2. Rotate in landscape mode                           *
    * DetailsFragment created with rand value 4769 restored *
    * Another DetailsFragment created for entry 6 (Othello) *
    * with new rand value 5572                              *
    *********************************************************
    
    D/DetailsActivity(21894): Entering onCreate
    D/DetailsActivity(21894): onCreate - landscape mode - finish
    
    D/DetailsFragment(21894): Entering onCreateView - this: DetailsFragment{4199d458 #0 id=0x1020002}
    D/DetailsFragment(21894): onCreateView - restored randValue: 4769
    
    D/FragmentLayout (Activity)(21894): Entering onCreate
    
    D/TitlesFragment(21894): Entering onCreateView
    D/TitlesFragment(21894): Entering onActivityCreated
    D/TitlesFragment(21894): onActivityCreated - landscape mode
    D/TitlesFragment(21894): onActivityCreated - dual pane, calling show details - position: 6
    D/TitlesFragment(21894): Entering showDetails - index: 6
    D/TitlesFragment(21894): showDetails - DetailsFragment found by id: null
    D/TitlesFragment(21894): showDetails - calling DetailsFragment newInstance for index: 6
    
    D/DetailsFragment(21894): Entering newInstance - index: 6
    D/DetailsFragment(21894): newInstance: DetailsFragment{419e16a8}
    D/DetailsFragment(21894): Entering onCreateView - this: DetailsFragment{419e16a8 #1 id=0x7f060004}
    D/DetailsFragment(21894): onCreateView - new mRandValue: 5572
    
    D/TitlesFragment(21894): Entering onStart
    D/TitlesFragment(21894): Entering onSaveInstanceState - save position: 6
    
    D/DetailsFragment(21894): Entering onSaveInstanceState - this: DetailsFragment{419e16a8 #1 id=0x7f060004}
    D/DetailsFragment(21894): onSaveInstanceState - save value: 5572
    
    
    *********************************************************
    * 3. Rotate back in portrait mode                       *
    * DetailsFragment created with rand value 5572 restored *
    * Select again item 6 (Othello)                         *
    * New DetailsFragment created with new rand value 5685  *
    * Both DetailsFragment save each its rand value         *
    *********************************************************
    
    D/FragmentLayout (Activity)(21894): Entering onCreate
    
    D/TitlesFragment(21894): Entering onCreateView
    D/TitlesFragment(21894): Entering onActivityCreated
    D/TitlesFragment(21894): onActivityCreated - portrait mode
    
    D/DetailsFragment(21894): Entering onCreateView - this: DetailsFragment{419e6248 #1 id=0x7f060004}
    D/DetailsFragment(21894): onCreateView - restored randValue: 5572
    
    D/TitlesFragment(21894): Entering onStart
    D/TitlesFragment(21894): Entering showDetails - index: 6
    D/TitlesFragment(21894): showDetails - Single Pane - start new activity
    D/TitlesFragment(21894): showDetails - position: 6 - title: Othello
    
    D/DetailsActivity(21894): Entering onCreate
    D/DetailsActivity(21894): onCreate - portrait mode
    D/DetailsActivity(21894): onCreate - new DetailsFragment: DetailsFragment{419bcf98}
    
    D/DetailsFragment(21894): Entering onCreateView - this: DetailsFragment{419bcf98 #0 id=0x1020002}
    D/DetailsFragment(21894): onCreateView - new mRandValue: 5685
    
    D/TitlesFragment(21894): Entering onSaveInstanceState - save position: 6
    
    D/DetailsFragment(21894): Entering onSaveInstanceState - this: DetailsFragment{419e6248 #1 id=0x7f060004}
    D/DetailsFragment(21894): onSaveInstanceState - save value: 5572
    D/DetailsFragment(21894): Entering onSaveInstanceState - this: DetailsFragment{419bcf98 #0 id=0x1020002}
    D/DetailsFragment(21894): onSaveInstanceState - save value: 5685
    
    
    ******************************************************************
    * 4. Rotate again in landscape mode                              *
    * DetailsFragment created with rand value 5685 restored          *
    * DetailsFragment found by id with same index 6, no new instance *
    * the found fragment is created with rand value 5572 restored,   *
    * this is the rand value visible in point 2.                     *
    ******************************************************************
    
    D/DetailsActivity(21894): Entering onCreate
    D/DetailsActivity(21894): onCreate - landscape mode - finish
    
    D/DetailsFragment(21894): Entering onCreateView - this: DetailsFragment{419c2fc0 #0 id=0x1020002}
    D/DetailsFragment(21894): onCreateView - restored randValue: 5685
    
    D/FragmentLayout (Activity)(21894): Entering onCreate
    
    D/TitlesFragment(21894): Entering onCreateView
    D/TitlesFragment(21894): Entering onActivityCreated
    D/TitlesFragment(21894): onActivityCreated - landscape mode
    D/TitlesFragment(21894): onActivityCreated - dual pane, calling show details - position: 6
    D/TitlesFragment(21894): Entering showDetails - index: 6
    D/TitlesFragment(21894): showDetails - DetailsFragment found by id: DetailsFragment{41a07e08 #1 id=0x7f060004}
    D/TitlesFragment(21894): showDetails - details.getShownIndex: 6
    
    D/DetailsFragment(21894): Entering onCreateView - this: DetailsFragment{41a07e08 #1 id=0x7f060004}
    D/DetailsFragment(21894): onCreateView - restored randValue: 5572
    
    D/TitlesFragment(21894): Entering onStart
    

    我做了一些修改的代码的一部分

    在TitlesFragment中

    public class TitlesFragment extends ListFragment
    {
        private final String TAG = "TitlesFragment";
    
        ...
        @Override
        public void onStart()
        {
            Log.d(TAG, "Entering onStart");
            super.onStart();
            if (mDualPane) {
                // call here because doesn't work when called in showDetails
                getListView().setItemChecked(mCurCheckPosition, true);
            }
        }
    
        ...
        void showDetails(int index) {
            Log.d(TAG, "Entering showDetails - index: " + index);
            mCurCheckPosition = index;
    
            if (mDualPane) {
                // We can display everything in-place with fragments, so update
                // the list to highlight the selected item and show the data.
                // This doesn't work here, moved in onStart
                //getListView().setItemChecked(index, true);
    
                // Check what fragment is currently shown, replace if needed.
                DetailsFragment details = (DetailsFragment)
                        getFragmentManager().findFragmentById(R.id.details);
                Log.d(TAG, "showDetails - DetailsFragment found by id: " + details);
                if (details != null) {
                    Log.d(TAG, "showDetails - details.getShownIndex: " + details.getShownIndex());
                }
    
                if (details == null || details.getShownIndex() != index) {
                    Log.d(TAG, "showDetails - calling DetailsFragment newInstance for index: " + index);
    
                    // Make new fragment to show this selection.
                    details = DetailsFragment.newInstance(index);
    
                    // Execute a transaction, replacing any existing fragment
                    // with this one inside the frame.
                    FragmentTransaction ft = getFragmentManager().beginTransaction();
                    //if (index == 0) {
                        ft.replace(R.id.details, details);
                    //} else {
                        // following crash!!
                        //ft.replace(R.id.a_item, details);
                    //}
                    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                    ft.commit();
                }
    
            } else {
                Log.d(TAG, "showDetails - Single Pane - start new activity");
                Log.d(TAG, "showDetails - position: " + index + " - title: " + getListAdapter().getItem(index));
    
                // Otherwise we need to launch a new activity to display
                // the dialog fragment with selected text.
                Intent intent = new Intent();
                intent.setClass(getActivity(), DetailsActivity.class);
                intent.putExtra("index", index);
                startActivity(intent);
            }
        }    
    }
    

    并在DetailsFragment中:

    public class DetailsFragment extends Fragment
    {
        private final String TAG = "DetailsFragment";
    
        private int mRandValue = 9999;
    
        ...
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState)
        {
            Log.d(TAG, "Entering onCreateView - this: " + this.toString());
    
            if (savedInstanceState != null) {
                mRandValue = savedInstanceState.getInt("randValue", 8888);
                Log.d(TAG, "onCreateView - restored randValue: " + mRandValue);
            }
    
            if (container == null) {
                // We have different layouts, and in one of them this
                // fragment's containing frame doesn't exist.  The fragment
                // may still be created from its saved state, but there is
                // no reason to try to create its view hierarchy because it
                // won't be displayed.  Note this is not needed -- we could
                // just run the code below, where we would create and return
                // the view hierarchy; it would just never be used.
                return null;
            }
    
            ScrollView scroller = new ScrollView(getActivity());
            TextView text = new TextView(getActivity());
            int padding = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                    4, getActivity().getResources().getDisplayMetrics());
            text.setPadding(padding, padding, padding, padding);
            scroller.addView(text);
            final int idx = getShownIndex();
            text.setText(Shakespeare.TITLES[idx] + "\n\n" + Shakespeare.DIALOGUE[idx]);
            //text.setText(Shakespeare.DIALOGUE[getShownIndex()]);
    
            // create a new random value to simultate an action in the fragment
            if (mRandValue > 7000) {
                mRandValue = (int)(System.currentTimeMillis() % 7000);
                Log.d(TAG, "onCreateView - new mRandValue: " + mRandValue);
            }
            text.append("\n\nRand Value = " + mRandValue);
    
            return scroller;
        }
    
        @Override
        public void onSaveInstanceState(Bundle _outState)
        {
            Log.d(TAG, "Entering onSaveInstanceState - this: " + this.toString());
            Log.d(TAG, "onSaveInstanceState - save value: " + mRandValue);
            super.onSaveInstanceState(_outState);
            _outState.putInt("randValue", mRandValue);
        }
    }
    

    我的问题

    我需要更改以正确处理旋转?
    'rand value'是我想要保留的DetailsFragment!

2 个答案:

答案 0 :(得分:0)

旋转重新创建您的活动您必须覆盖onsaved实例并保存其中所需的值....... 然后在onResume()方法中,您可以获取这些值

答案 1 :(得分:0)

也许最好在putInt之后调用super.onSaveInstanceState:

@Override
public void onSaveInstanceState(Bundle _outState)
{
    Log.d(TAG, "Entering onSaveInstanceState - this: " + this.toString());
    Log.d(TAG, "onSaveInstanceState - save value: " + mRandValue);

    **_outState.putInt("randValue", mRandValue);**
    super.onSaveInstanceState(_outState);

}