android fragment—当另一个片段被推到片段上时,如何在片段中保存视图状态

android fragment—当另一个片段被推到片段上时,如何在片段中保存视图状态,android,android-fragments,Android,Android Fragments,在android中,一个片段(比如说FragA)被添加到backbackback,另一个片段(比如说FragB)被添加到顶部。现在,回击一下FragA会显示在顶部,并调用onCreateView()。现在,在FragB被推到它上面之前,我的FragA处于特定的状态 我的问题是如何将FragA恢复到以前的状态?是否有一种保存状态的方法(比如在捆绑包中),如果有,那么我应该覆盖哪种方法?在FragmentList示例中,您可以找到: @Override public void onSaveInsta

在android中,一个片段(比如说
FragA
)被添加到backbackback,另一个片段(比如说
FragB
)被添加到顶部。现在,回击一下
FragA
会显示在顶部,并调用
onCreateView()
。现在,在
FragB
被推到它上面之前,我的
FragA
处于特定的状态

我的问题是如何将FragA恢复到以前的状态?是否有一种保存状态的方法(比如在捆绑包中),如果有,那么我应该覆盖哪种方法?

在FragmentList示例中,您可以找到:

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt("curChoice", mCurCheckPosition);
}
您以后可以这样使用:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    if (savedInstanceState != null) {
        // Restore last state for checked position.
        mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
    }
}
我是碎片方面的初学者,但这似乎解决了你的问题;)
OnActivityCreated在片段从后堆栈返回后被调用。

如果您正在处理android清单中指定的片段活动中的配置更改,如下所示

<activity
    android:name=".courses.posts.EditPostActivity"
    android:configChanges="keyboardHidden|orientation"
    android:screenOrientation="unspecified" />


然后片段的
onSaveInstanceState
将不会被调用,而
savedInstanceState
对象将始终为空。

我处理的问题与此非常类似。因为我知道我会经常返回到前一个片段,所以我检查片段
.isAdded()
是否为真,如果为真,则不执行
事务。replace()
我只执行
事务。show()
。如果片段已经在堆栈上,这可以防止其被重新创建-无需保存状态

Fragment target = <my fragment>;
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
if(target.isAdded()) {
    transaction.show(target);
} else {
    transaction.addToBackStack(button_id + "stack_item");
    transaction.replace(R.id.page_fragment, target);
}
transaction.commit();
在Android 3.0及更高版本中,
屏幕大小显然是必需的


祝你好运

请注意,如果您使用ViewPager处理片段,这非常简单。您只需要调用此方法:
setOffscreenPageLimit()

根据文件:

设置在空闲状态下视图层次结构中当前页面两侧应保留的页数。超出此限制的页面将在需要时从适配器重新创建


除非片段的活动调用其自身和附加片段,否则将永远不会调用片段的
onSaveInstanceState(Bundle outState)
。因此,只有在某些东西(通常是旋转)强制活动
SaveInstanceState
并在以后还原它时,才会调用此方法。 但是,如果只有一个活动和一大组片段在其中(大量使用
replace
),并且应用程序仅在一个方向上运行,那么saveInstanceState(Bundle outState)上的
可能很长时间都不会被调用

我知道三种可能的解决办法

第一:

使用片段的参数保存重要数据:

public class FragmentA extends Fragment {
    private static final String PERSISTENT_VARIABLE_BUNDLE_KEY = "persistentVariable";

    private EditText persistentVariableEdit;

    public FragmentA() {
        setArguments(new Bundle());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_a, null);

        persistentVariableEdit = (EditText) view.findViewById(R.id.editText);

        TextView proofTextView = (TextView) view.findViewById(R.id.textView);

        Bundle mySavedInstanceState = getArguments();
        String persistentVariable = mySavedInstanceState.getString(PERSISTENT_VARIABLE_BUNDLE_KEY);

        proofTextView.setText(persistentVariable);


        view.findViewById(R.id.btnPushFragmentB).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getFragmentManager()
                        .beginTransaction()
                        .replace(R.id.frameLayout, new FragmentB())
                        .addToBackStack(null)
                        .commit();
            }
        });

        return view;
    }

    @Override
    public void onPause() {
        super.onPause();
        String persistentVariable = persistentVariableEdit.getText().toString();

        getArguments().putString(PERSISTENT_VARIABLE_BUNDLE_KEY, persistentVariable);
    }
}
第二种但不那么迂腐的方式- 在单例中保存变量


第三个-不要
replace()
片段,而是
add()
/
show()
/
隐藏()
它们。

我对包含列表视图的片段使用了混合方法。这似乎很有效,因为我没有替换当前片段,而是添加新片段并隐藏当前片段。在承载片段的活动中,我有以下方法:

private ViewPager viewPager;
viewPager = (ViewPager) findViewById(R.id.pager);
mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        @Override
        public void onPageSelected(int position) {
            // on changing the page
            // make respected tab selected
            actionBar.setSelectedNavigationItem(position);
        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {
        }
    });
}

@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
    // on tab selected
    // show respected fragment view
    viewPager.setCurrentItem(tab.getPosition());
}

@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
public void addFragment(Fragment currentFragment, Fragment targetFragment, String tag) {
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.setCustomAnimations(0,0,0,0);
    transaction.hide(currentFragment);
    // use a fragment tag, so that later on we can find the currently displayed fragment
    transaction.add(R.id.frame_layout, targetFragment, tag)
            .addToBackStack(tag)
            .commit();
}
每当单击/点击列表项时(因此我需要启动/显示详细信息片段),我都会在片段(包含列表视图)中使用此方法:

getFragmentTags()
返回一个字符串数组,我在添加新片段时将其用作不同片段的标记(请参见上文
addFragment
方法中的
transaction.add
方法)

在包含列表视图的片段中,我在其onPause()方法中执行此操作:

然后在片段的onCreateView中(实际上是在onCreateView中调用的方法中),我恢复状态:

// Restore previous state (including selected item index and scroll position)
if(mListViewState != null) {
    Log.d(TAG, "Restoring the listview's state.");
    lv.onRestoreInstanceState(mListViewState);
}

我找到的最佳解决方案如下:

onSavedInstanceState():当活动要关闭时(将活动从一个移动到另一个或配置更改),始终在片段内调用。 因此,如果我们在同一活动上调用多个片段,那么我们必须使用以下方法:

使用片段的OnDestroyView()并将整个对象保存在该方法中。 然后 OnActivityCreated():检查对象是否为null(因为此方法每次都调用)。现在在这里恢复一个对象的状态


它总是有用的

我认为
onSaveInstanceState
不是一个好的解决方案。它只用于已被破坏的活动

从android 3.0开始,Fragmen已经被FragmentManager管理,条件是:一个活动映射manny片段,当片段在backStack中添加(不是替换:它将重新创建)时,视图将被取消存储。当返回到最后一个时,它将像以前一样显示


因此,我认为FragmentManager和事务足以处理它。

在尝试了许多复杂的解决方案之后,我只需要保存/恢复片段中的单个值(EditText的内容),尽管这可能不是最优雅的解决方案,创建共享引用并在其中存储我的状态对我很有效

只需膨胀一下您的视图。

举例如下:

public class AFragment extends Fragment {

private View mRootView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    if(mRootView==null){
        mRootView = inflater.inflate(R.id.fragment_a, container, false);
        //......
    }
    return mRootView;
}

}

在活动中保持不同片段中字段值的简单方法

创建片段实例并添加,而不是替换和删除

    FragA  fa= new FragA();
    FragB  fb= new FragB();
    FragC  fc= new FragB();
    fragmentManager = getSupportFragmentManager();
    fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.add(R.id.fragmnt_container, fa);
    fragmentTransaction.add(R.id.fragmnt_container, fb);
    fragmentTransaction.add(R.id.fragmnt_container, fc);
    fragmentTransaction.show(fa);
    fragmentTransaction.hide(fb);
    fragmentTransaction.hide(fc);
    fragmentTransaction.commit();
然后只显示和隐藏片段,而不是再次添加和删除片段

    fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.hide(fa);
    fragmentTransaction.show(fb);
    fragmentTransaction.hide(fc);
    fragmentTransaction.commit()

)

我无法让它工作savedInstanceState始终为空。我通过xml布局添加片段。必须将mCurCheckPosition更改为static,然后它才能工作,但感觉有问题。它不调用saveInstanceState-为什么要调用它?所以,这种方法不起作用。如果我们想在同一活动中从另一个片段返回时保留片段状态,这种方法真的会起作用吗?onSaveInstanceState()仅在活动onPause/onStop事件上被调用。根据文献记载:“也像ac
public class AFragment extends Fragment {

private View mRootView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    if(mRootView==null){
        mRootView = inflater.inflate(R.id.fragment_a, container, false);
        //......
    }
    return mRootView;
}
    FragA  fa= new FragA();
    FragB  fb= new FragB();
    FragC  fc= new FragB();
    fragmentManager = getSupportFragmentManager();
    fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.add(R.id.fragmnt_container, fa);
    fragmentTransaction.add(R.id.fragmnt_container, fb);
    fragmentTransaction.add(R.id.fragmnt_container, fc);
    fragmentTransaction.show(fa);
    fragmentTransaction.hide(fb);
    fragmentTransaction.hide(fc);
    fragmentTransaction.commit();
    fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.hide(fa);
    fragmentTransaction.show(fb);
    fragmentTransaction.hide(fc);
    fragmentTransaction.commit()