如何使用 onSaveInstanceState 在我的片段上保存和恢复接口
Posted
技术标签:
【中文标题】如何使用 onSaveInstanceState 在我的片段上保存和恢复接口【英文标题】:How to save and restore an interface on my fragment using onSaveInstanceState 【发布时间】:2015-08-07 02:39:41 【问题描述】:当我的片段重新加载时,我需要恢复变量。除了我的回调之外,所有其他变量都在工作。
我有一个这样的片段:
公共类 ClosetFragment 扩展片段
private String [] closetSessions = null;
private DBName dbName = null;
private String token = null;
private RefreshCallback callback= null;
public ClosetFragment(String [] closetSessions, DBName dbName, String token, RefreshCallback callback)
this.closetSessions = closetSessions;
this.dbName = dbName;
this.token = token;
this.callback = callback;
public ClosetFragment()
@Override
public void onSaveInstanceState(final Bundle outState)
super.onSaveInstanceState(outState);
outState.putSerializable("closetSessions", (Serializable) this.closetSessions);
outState.putSerializable("dbName", (Serializable) this.dbName);
outState.putSerializable("token", (Serializable) this.token);
outState.putSerializable("callback", (Serializable) this.callback);
我的回调是:
public interface RefreshCallback extends Serializable
public void onNeedrefresh();
我得到的例外是:
AppSectionsPagerAdapter 是实现我的回调的类。
05-25 12:04:06.037: E/androidRuntime(10822): FATAL EXCEPTION: main
05-25 12:04:06.037: E/AndroidRuntime(10822): java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = br.com.closet4share.app.adapters.AppSectionsPagerAdapter$1)
05-25 12:04:06.037: E/AndroidRuntime(10822): at android.os.Parcel.writeSerializable(Parcel.java:1279)
05-25 12:04:06.037: E/AndroidRuntime(10822): at android.os.Parcel.writeValue(Parcel.java:1233)
05-25 12:04:06.037: E/AndroidRuntime(10822): at android.os.Parcel.writeMapInternal(Parcel.java:591)
05-25 12:04:06.037: E/AndroidRuntime(10822): at android.os.Bundle.writeToParcel(Bundle.java:1627)
05-25 12:04:06.037: E/AndroidRuntime(10822): at android.os.Parcel.writeBundle(Parcel.java:605)
05-25 12:04:06.037: E/AndroidRuntime(10822): at android.support.v4.app.FragmentState.writeToParcel(Fragment.java:135)
05-25 12:04:06.037: E/AndroidRuntime(10822): at android.os.Parcel.writeTypedArray(Parcel.java:1102)
05-25 12:04:06.037: E/AndroidRuntime(10822): at android.support.v4.app.FragmentManagerState.writeToParcel(FragmentManager.java:378)
05-25 12:04:06.037: E/AndroidRuntime(10822): at android.os.Parcel.writeParcelable(Parcel.java:1254)
05-25 12:04:06.037: E/AndroidRuntime(10822): at android.os.Parcel.writeValue(Parcel.java:1173)
05-25 12:04:06.037: E/AndroidRuntime(10822): at android.os.Parcel.writeMapInternal(Parcel.java:591)
05-25 12:04:06.037: E/AndroidRuntime(10822): at android.os.Bundle.writeToParcel(Bundle.java:1627)
05-25 12:04:06.037: E/AndroidRuntime(10822): at android.os.Parcel.writeBundle(Parcel.java:605)
05-25 12:04:06.037: E/AndroidRuntime(10822): at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:2535)
05-25 12:04:06.037: E/AndroidRuntime(10822): at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3151)
非常感谢您的帮助!
这就是我实现回调的方式:
@Override
public Fragment getItem(int i)
Fragment fragment = null;
fragment = new ClosetFragment(i,closetSessions,dbName,token, new RefreshCallback()
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public void onNeedrefresh()
AppSectionsPagerAdapter.this.notifyDataSetChanged();
);
mPageReferences.put(i, new WeakReference<Fragment>(fragment));
return fragment;
【问题讨论】:
您能否在示例中编辑您如何使用实例化此callback
?例如。 AppSectionsPagerAdapter
中的实现。
【参考方案1】:
发生异常是因为匿名内部类包含父适配器的成员变量 - 这是您通过 AppSectionsPagerAdapter.this
访问的,并且适配器不可序列化。
您不能以这种方式持续回调,老实说,您甚至不应该尝试这样做。只持久化Fragment内部的数据,在getItem
中单独设置回调。
【讨论】:
但是当片段暂停和恢复时,它不会调用 getItem。我对回调的引用丢失了。所以如果我要改变这个架构,我怎么能告诉我的适配器从 fagment 内部 notifyDataSetChanged 呢? @vzsg【参考方案2】:在我的活动中,我创建了方法:
public void refreshAdapter()
if (mAppSectionsPagerAdapter != null)
mAppSectionsPagerAdapter.notifyDataSetChanged();
在我的 Fragment 中调用:
Closet closet = (Closet)getActivity();
closet.refreshAdapter();
而且不需要保存任何东西。谢谢@vzsg。
【讨论】:
这也有效。需要注意的一件事是,如果 Fragment 已分离,getActivity()
可能会返回 null,因此您必须小心使用可能比 Activity 寿命更长的 AsyncTasks。【参考方案3】:
public class MainActivity extends Activity implements AddToDoFragment.OnToDoAddedListener
private ArrayList<String> todoItems;
private ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState == null)
todoItems = new ArrayList<String>();
else
todoItems = savedInstanceState.getStringArrayList("todoItemTag");//the tag must match what the variable was saved with
FragmentManager fm = getFragmentManager();
ToDoListFragment listToDo = new ToDoListFragment();
listToDo = (ToDoListFragment) fm.findFragmentById(R.id.list_view_fragment);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, todoItems);
listToDo.setListAdapter(adapter);
public void OnToDoAdded(String newToDo)
todoItems.add(newToDo);
adapter.notifyDataSetChanged();
@Override
protected void onSavedInstanceState(Bundle outState)
super.onSaveInstanceState(outState);
oustate.putStringArrayList("todoItemTag", todoItems);//it would be advised to make the tags a static final String
您需要重写 onSavedInstanceState 方法,以便知道何时需要保存状态。然后,您还需要更新 onCreate 方法以检查 savedInstanceState 是否为空。如果它为空,则该活动尚未启动。这是您的 MainActivity 类的示例,您可以从那里开始:
【讨论】:
您好,savedInstanceState 不为空,即使我没有签入此代码,活动也已启动。问题是如何保存和恢复我的回调?如何放置它并从 savedInstanceState 中检索它?以上是关于如何使用 onSaveInstanceState 在我的片段上保存和恢复接口的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 onSaveInstanceState android 方向更改
如何将数据从 onCreate() 传递到 onSaveInstanceState()?
如何在活动的 onSaveInstanceState() 之后杀死所有打开的片段
我如何知道是不是调用了 onSaveInstanceState() 以避免 IllegalStateException?