Java 片段中未调用 onSaveInstanceState
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20892118/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
onSaveInstanceState is not being called in Fragment
提问by user3155092
I know that people have asked this question, but I followed all the answers and I still have the same problem. I have two scripts One is the fragment manager (IngredientsActivity) and the other is the fragment (OtherList). The code is as follows
我知道人们已经问过这个问题,但是我按照所有答案进行操作,但仍然遇到同样的问题。我有两个脚本一个是片段管理器(IngredientsActivity),另一个是片段(OtherList)。代码如下
IngredientsActivity
配料活动
import java.util.ArrayList;
import android.app.ActionBar;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class IngredientsActivity extends FragmentActivity implements ActionBar.TabListener {
private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.check_list);
// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// For each of the sections in the app, add a tab to the action bar.
actionBar.addTab(actionBar.newTab().setText("Alcahol").setTabListener(this));
actionBar.addTab(actionBar.newTab().setText("Juice").setTabListener(this));
actionBar.addTab(actionBar.newTab().setText("Other").setTabListener(this));
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
getActionBar().setSelectedNavigationItem(savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); //OVERRIDE SAVE ON MAINCLASS
outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, getActionBar().getSelectedNavigationIndex());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
if (tab.getPosition() == 0) {
AlcoholList simpleListFragment = new AlcoholList();
getSupportFragmentManager().beginTransaction().replace(R.id.containert, simpleListFragment).commit();
}
else if (tab.getPosition() == 1) {
JuiceList androidlidt = new JuiceList();
getSupportFragmentManager().beginTransaction().replace(R.id.containert, androidlidt).commit();
}
else {
OtherList androidversionlist = new OtherList();
getSupportFragmentManager().beginTransaction().replace(R.id.containert, androidversionlist).commit();
}
}
@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
public static class DummySectionFragment extends Fragment {
public DummySectionFragment() {
}
public static final String ARG_SECTION_NUMBER = "section_number";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
TextView textView = new TextView(getActivity());
textView.setGravity(Gravity.CENTER);
Bundle args = getArguments();
textView.setText(Integer.toString(args.getInt(ARG_SECTION_NUMBER)));
return textView;
}
}
}
OtherList
其他列表
import java.util.ArrayList;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.ListView;
public class OtherList extends ListFragment{
MyCustomAdapter dataAdapter = null;
private ArrayList<String> recipesList;
private ArrayList<Items> stateList ;
public OtherList() {
setRetainInstance(true);
stateList = new ArrayList<Items>();
Items _states1 = new Items ("Gin",false);
stateList.add(_states1);
Items _states2 = new Items ("Ginger Liqueur",false);
stateList.add(_states2);
Items _states3 = new Items ("Citrus Vodka",false);
stateList.add(_states3);
Items _states4 = new Items ("Champagne",false);
stateList.add(_states4);
Items _states5 = new Items ("Coconut Rum",false);
stateList.add(_states5);
Items _states6 = new Items ("Pear Vodka",false);
stateList.add(_states6);
Items _states7 = new Items ("Rum",false);
stateList.add(_states7);
Items _states8 = new Items ("Tequila",false);
stateList.add(_states8);
Items _states9 = new Items ("Triple Sec",false);
stateList.add(_states9);
Items _states10 = new Items ("Kahlua",false);
stateList.add(_states10);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dataAdapter = new MyCustomAdapter(this.getActivity(),R.layout.da_item, stateList);
setListAdapter(dataAdapter);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.list_fragment, container, false);
}
@Override
public void onListItemClick(ListView list, View v, int position, long id) {
}
private class MyCustomAdapter extends ArrayAdapter<Items>
{
private ArrayList<Items> stateList;
public MyCustomAdapter(Context context, int textViewResourceId,
ArrayList<Items> stateList)
{
super(context, textViewResourceId, stateList);
this.stateList = new ArrayList<Items>();
this.stateList.addAll(stateList);
}
private class ViewHolder
{
CheckBox name;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder = null;
Log.v("ConvertView", String.valueOf(position));
if (convertView == null)
{
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.da_item, null);
holder = new ViewHolder();
holder.name = (CheckBox) convertView.findViewById(R.id.ingredientbox);
convertView.setTag(holder);
holder.name.setOnClickListener( new View.OnClickListener()
{
public void onClick(View v)
{
CheckBox cb = (CheckBox) v;
Items _state = (Items) cb.getTag();
_state.setSelected(cb.isChecked());
}
});
}
else
{
holder = (ViewHolder) convertView.getTag();
}
Items state = stateList.get(position);
holder.name.setText(state.getName());
holder.name.setChecked(state.isSelected());
holder.name.setTag(state);
return convertView;
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
}
@Override
public void onSaveInstanceState(Bundle outState) {
Log.d("hey","SAVING"); //NOT SAVING
super.onSaveInstanceState(outState);
save();
outState.putStringArrayList("index", recipesList);
}
}
}
}
}
I found multiple suggestions that said to override the onSaveInstanceState , which I did and I found even more telling me to use setRetainInstance. I don't know why setRetainInstance state would be helpful if I want to save a value of a list. My question-Why Is it not calling the save in the OtherList class or whats a better method to implement if I want to save the values in the List View(in this case I am using checkboxes)
我发现了多个建议,说要覆盖 onSaveInstanceState ,我做到了,我发现更多的建议告诉我使用 setRetainInstance。如果我想保存列表的值,我不知道为什么 setRetainInstance 状态会有所帮助。我的问题 - 如果我想在列表视图中保存值,为什么它不调用 OtherList 类中的保存,或者有什么更好的方法来实现(在这种情况下我使用复选框)
采纳答案by Steve M
onSaveInstanceState()
is only called when the Android system may need to recreate that particular instance of the Fragment. There are many instances of navigating away from the Fragment or even destroying the Fragment where it will not be called. Please consult the documentation for more information, please read the Activity.onSaveInstanceState()
documentation as well since that applys here also: http://developer.android.com/reference/android/app/Fragment.html#onSaveInstanceState(android.os.Bundle)http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)
onSaveInstanceState()
仅在 Android 系统可能需要重新创建 Fragment 的特定实例时调用。有很多情况下导航离开 Fragment 甚至在不会调用 Fragment 的地方销毁 Fragment。请查阅文档以获取更多信息,也请阅读Activity.onSaveInstanceState()
文档,因为这也适用于此处:http: //developer.android.com/reference/android/app/Fragment.html#onSaveInstanceState(android.os.Bundle) http: //developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)
EDIT: In your case, you must not recreate the fragment every time the user navigates back to the fragment. I recommend considering ViewPager and FragmentPagerAdapter to automatically manage the fragments. Also look at this post: ViewPager and fragments — what's the right way to store fragment's state?
编辑:在您的情况下,每次用户导航回片段时,您都不得重新创建片段。我建议考虑使用 ViewPager 和 FragmentPagerAdapter 来自动管理片段。另请查看这篇文章:ViewPager 和片段 — 存储片段状态的正确方法是什么?
回答by dt0
I had a similar problem where I was trying to get a Fragment to save its state but onSaveInstanceState() wasn't being called on FragmentTransaction.replace(). I was trying to find a solution for this and thought, if the Fragment itself can't save its own state then can't whatever is doing the replacing save it. So I did something like this:
我有一个类似的问题,我试图让一个 Fragment 来保存它的状态,但没有在 FragmentTransaction.replace() 上调用 onSaveInstanceState()。我试图为此找到解决方案,并认为,如果 Fragment 本身无法保存自己的状态,则无法进行替换保存它。所以我做了这样的事情:
In the Fragment have a method called getState() or whatever you want:
在 Fragment 中有一个名为 getState() 或任何你想要的方法:
public Bundle getState()
{
// save whatever you would have in onSaveInstanceState() and return a bundle with the saved data
}
Then in the hosting object, save that bundle to its instance variables before replacing the Fragment and set the argument to that saved bundle when switching back.
然后在托管对象中,在替换 Fragment 之前将该包保存到其实例变量,并在切换回来时将参数设置为该保存的包。
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
// assume Fragment a exists and you're trying to save the state and "state" is an instance variable
state = a.getState();
ft.replace(android.R.id.content, b);
Then when swapping back to Fragment a you would pass the bundle as an argument.
然后当交换回 Fragment a 时,您会将包作为参数传递。
a.setArguments(state);
ft.replace(android.R.id.content, a);
I didn't look into your code too deeply but it sounds similar to the problem I had from your description.
我没有深入研究您的代码,但听起来与我从您的描述中遇到的问题相似。