如何使用 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?

如果我使用 SharedPreferences,使用 onSaveInstanceState 是不是有用

onSaveInstanceState() 和 onRestoreInstanceState()