为什么我的 listfragment 不保留其状态?

Why isn't my listfragment retaining its state?

我正在练习片段,所以我尝试将一个 ListFragment 添加到我的 MainActivity。没什么难的,只是一个列表,其中每一行都有一个名称和一个数字,您可以使用 plus/minus 按钮 increase/decrease。但是,当我旋转屏幕时,所有数字都重置为 0。

MyListFragment.java

package randomdomain.dialogtest;

import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

public class MyListFragment extends ListFragment {
    public static final String MYOBJECT_PARCELABLE_KEY = "myobject_parcelable_key";
    private MyAdapter mMyAdapter;
    private List<MyObject> mMyObjects;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View contentView = inflater.inflate(R.layout.list_fragment, container, false);

        mMyObjects = fillObjects();
        mMyAdapter = new MyAdapter(getActivity(), mMyObjects);
        setListAdapter(mMyAdapter);

        return contentView;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        for (int i = 0; i < mMyObjects.size(); i++)
            outState.putParcelable(MYOBJECT_PARCELABLE_KEY + i, mMyObjects.get(i));
    }

    @Override
    public void onViewStateRestored(Bundle savedInstanceState) {
        super.onViewStateRestored(savedInstanceState);
        mMyObjects = new ArrayList<MyObject>();
        for (int i = 0; i < mMyObjects.size(); i++) {
            MyObject object = savedInstanceState.getParcelable(MYOBJECT_PARCELABLE_KEY + i);
            mMyObjects.add(object);
        }
    }

    private List<MyObject> fillObjects() {
        List<MyObject> myObjects = new ArrayList<MyObject>();
        for (int i = 0; i < 30; i++) {
            MyObject object = new MyObject("Object " + (i + 1) + " ", 0);
            myObjects.add(object);
        }
        return myObjects;
    }
}

MyObject.java 如果需要:

package randomdomain.dialogtest;

import android.os.Parcel;
import android.os.Parcelable;

public class MyObject implements Parcelable {
    private String mName;
    private int mValue;

    public MyObject(String name, int value) {
        mName = name;
        mValue = value;
    }

    public String getName() {
        return mName;
    }

    public void setName(String name) {
        mName = name;
    }

    public int getValue() {
        return mValue;
    }

    public void setValue(int value) {
        mValue = value;
    }

    @Override
    public int describeContents() {
        return 0; // nothing
    }

    private MyObject(Parcel in) {
        mName = in.readString();
        mValue = in.readInt();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mName);
        dest.writeInt(mValue);
    }

    public static final Creator<MyObject> CREATOR = new Creator<MyObject>() {
        @Override
        public MyObject createFromParcel(Parcel source) {
            return new MyObject(source);
        }

        @Override
        public MyObject[] newArray(int size) {
            return new MyObject[size];
        }
    };
}

和 MyAdapter.java,如果需要,再次:

package randomdomain.dialogtest;


import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;

import java.util.List;

public class MyAdapter extends BaseAdapter {
    private Context mContext;
    private List<MyObject> mMyObjects;

    public MyAdapter(Context context, List<MyObject> objects) {
        mContext = context;
        mMyObjects = objects;
    }

    @Override
    public int getCount() {
        return mMyObjects.size();
    }

    @Override
    public Object getItem(int position) {
        return mMyObjects.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0; //unused
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;

        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_row, null);
            holder = new ViewHolder();
            holder.rowName = (TextView) convertView.findViewById(R.id.text_rowname);
            holder.counter = (TextView) convertView.findViewById(R.id.text_counter);
            holder.buttonAdd = (Button) convertView.findViewById(R.id.button_add);
            holder.buttonSubtract = (Button) convertView.findViewById(R.id.button_subtract);
            convertView.setTag(holder);
        }
        else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.rowName.setText(mMyObjects.get(position).getName());
        holder.counter.setText(mMyObjects.get(position).getValue() + "");
        holder.buttonSubtract.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mMyObjects.get(position).setValue(Math.max(mMyObjects.get(position).getValue() - 1, 0));
                holder.counter.setText(mMyObjects.get(position).getValue() + "");
            }
        });
        holder.buttonAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mMyObjects.get(position).setValue(mMyObjects.get(position).getValue() + 1);
                holder.counter.setText(mMyObjects.get(position).getValue()+ "");
            }
        });
        return convertView;
    }

    private static class ViewHolder {
        public TextView rowName;
        public TextView counter;
        public Button buttonSubtract;
        public Button buttonAdd;
    }
}

而 MainActivity 只是调用片段:

package randomdomain.dialogtest;

import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.add(R.id.fragment_container, new MyListFragment()).commit();
    }
}

为什么即使我已经扩展了 Parcelable 并在保存时保存了所有值,然后在恢复时使用保存的实例状态重置了列表?

编辑,已更新 MyListFragment.java

package randomdomain.dialogtest;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

public class MyListFragment extends ListFragment {
    public static final String MYOBJECT_PARCELABLE_KEY = "myobject_parcelable_key";
    private MyAdapter mMyAdapter;
    private List<MyObject> mMyObjects;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View contentView = inflater.inflate(R.layout.list_fragment, container, false);

        if (savedInstanceState == null) {
            mMyObjects = fillObjects();
        }
        else {
            mMyObjects = savedInstanceState.getParcelableArrayList(MYOBJECT_PARCELABLE_KEY);
        }

        mMyAdapter = new MyAdapter(getActivity(), mMyObjects);
        setListAdapter(mMyAdapter);

        return contentView;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putParcelableArrayList(MYOBJECT_PARCELABLE_KEY, (ArrayList<MyObject>) mMyObjects);
        super.onSaveInstanceState(outState);
    }

    private List<MyObject> fillObjects() {
        List<MyObject> myObjects = new ArrayList<MyObject>();
        for (int i = 0; i < 30; i++) {
            MyObject object = new MyObject("Object " + (i + 1) + " ", 0);
            myObjects.add(object);
        }
        return myObjects;
    }
}

尝试将以下代码放入您的片段中:

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);
  }

如果 FragmentManager 找不到现有实例,请更改 onCreate() 以仅添加 Fragment 的新实例:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (getSupportFragmentManager().findFragmentById(R.id.fragment_container) == null )
    {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.add(R.id.fragment_container, new MyListFragment()).commit();
    }
}