【问题标题】:Android. Fragments not saving their states安卓。片段不保存其状态
【发布时间】:2014-08-26 06:12:57
【问题描述】:

我正在尝试创建自定义标签导航。单击每个选项卡时,它将替换屏幕中的片段。在 MainActivity.java 上,我正在为每个片段创建一个副本(我认为,通过这种方式,我可以在任何地方使用每个片段的一个副本)。

    public static WhereRootFragment whereRootFragment;
    public static FeedRootFragment feedRootFragment;

    public static WhereMainFragment whereMainFragment;
    public static FeedMainFragment feedMainFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
.....
        whereRootFragment=new WhereRootFragment();
        feedRootFragment=new FeedRootFragment();

        whereMainFragment=new WhereMainFragment();
        feedMainFragment=new FeedMainFragment();

        ClickHandler.handleClick(MainActivity.this, llWhere);
}

当标签按钮被点击时,它用当前片段替换旧片段(handleClick方法)。

        switch (tag) {
        case TAG_WHERE:
            MainActivity.ivWhere.setImageDrawable(a.getResources().getDrawable(
                    R.drawable.where_black));
//          Fragment fragment_where_root=new WhereRootFragment();
            FragmentTransaction transaction_where = ((FragmentActivity) a).getSupportFragmentManager().beginTransaction();
            transaction_where.replace(R.id.root_frame, MainActivity.whereRootFragment);
            transaction_where.addToBackStack(null);
            transaction_where.commit();
            break;
        case TAG_FEED:
            MainActivity.ivFeed.setImageDrawable(a.getResources().getDrawable(
                    R.drawable.feed_black));
//          Fragment fragment_feed_root=new FeedRootFragment();
            FragmentTransaction transaction_feed = ((FragmentActivity) a).getSupportFragmentManager().beginTransaction();
            transaction_feed.replace(R.id.root_frame,  MainActivity.feedRootFragment);
            transaction_feed.addToBackStack(null);
            transaction_feed.commit();
            break;

WhereRootFragment:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    /* Inflate the layout for this fragment */
    View view = inflater.inflate(R.layout.fragment_where_root, container, false);

    FragmentTransaction transaction = getFragmentManager()
            .beginTransaction();
    transaction.replace(R.id.where_root_frame, MainActivity.whereMainFragment);
    transaction.addToBackStack(null);
    transaction.commit();

    return view;
}

WhereMainFragment

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

结果:

[StartApp]->[1.Where:showing]->[2.Feed:showing]->[3.Where:不显示]->[4.Feed:显示保存状态]->[ 5.另一个片段:应该是空的]->[6.Feed:不显示]

问题:如何解决这个问题?如何让fragment保存状态?

【问题讨论】:

  • 从 onClick 事件中移除 transaction_feed.addToBackStack(null);
  • @PratikButani,我已经按照你说的尝试过,但没有帮助
  • WhereRootFragment 而不是 getFragmentManager 使用 getChildFragmentManager, as WhereMainFragment` 是 WhereRootFragment 的子级。

标签: java android android-fragments


【解决方案1】:

WhereRootFragment 由属于活动的片段管理器管理。问题正在发生,因为相同的片段管理器被用于管理WhereMainFragment,它是WhereRootFragment 的子级。

WhereMainFragment 应该由属于WhereRootFragment 的片段管理器管理。要在片段中获取子片段管理器,请使用Fragment.getChildFragmentManager

WhereRootFragment

public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    /* Inflate the layout for this fragment */
    View view = inflater.inflate(R.layout.fragment_where_root, container, false);

    // Use child fragment manager to manage WhereMainFragment
    FragmentTransaction transaction = getChildFragmentManager()
            .beginTransaction();
    transaction.replace(R.id.where_root_frame, MainActivity.whereMainFragment);
    transaction.addToBackStack(null);
    transaction.commit();

    return view;
}

【讨论】:

    【解决方案2】:

    有些链接可能对您有用:

    -> 你可能必须使用FragmentTabHost | Android Developers

    ->Creating-and-Using-Fragments

    ->你可能想要这个Android Fragments

    -> 最好的Android Beginner

    Stackoverflow Answer says:

    public final class MyFragment extends Fragment {
        private TextView vstup;
        private Bundle savedState = null;
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.whatever, null);
            vstup = (TextView)v.findViewById(R.id.whatever);
    
            /* (...) */
    
            /* If the Fragment was destroyed inbetween (screen rotation), we need to recover the savedState first */
            /* However, if it was not, it stays in the instance from the last onDestroyView() and we don't want to overwrite it */
            if(savedInstanceState != null && savedState == null)
                savedState = savedInstanceState.getBundle(App.STAV);
            if(savedState != null)
                vstup.setText(savedState.getCharSequence(App.VSTUP));
            savedState = null;
    
            return v;
        }
    
        @Override
        public void onDestroyView() {
            super.onDestroyView();
            savedState = saveState(); /* vstup defined here for sure */
            vstup = null;
        }
    
        private Bundle saveState() { /* called either from onDestroyView() or onSaveInstanceState() */
            Bundle state = new Bundle();
            state.putCharSequence(App.VSTUP, vstup.getText());
            return state;
        }
    
        @Override
        public void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            /* If onDestroyView() is called first, we can use the previously savedState but we can't call saveState() anymore */
            /* If onSaveInstanceState() is called first, we don't have savedState, so we need to call saveState() */
            /* => (?:) operator inevitable! */
            outState.putBundle(App.STAV, savedState != null ? savedState : saveState());
        }
    
        /* (...) */
    
    }
    

    【讨论】:

    • 谢谢你的回答,但这种方式不适合我。因为每个片段将包含许多视图,在其他片段中。有没有办法在不恢复每个视图的状态的情况下自动处理这个问题?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多