为什么我的 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();
}
}
我正在练习片段,所以我尝试将一个 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();
}
}