为什么这种保存和恢复自定义数组列表的parcelables实现不起作用



我用Volley从json中获取数据,并用解析后的数据填充RecyclerView,但我遇到了一点问题:获取项的调用在onCreate方法中,因此每次从配置更改和其他方面重新创建活动时都会重复该调用;因此数据被重新加载。所以我找到了这个使用parcelables的答案以及这篇关于Codepath的文章(仍然是关于parcelables的)。在我明确地遵循了说明之后(或者我觉得是这样),似乎没有什么变化:每次重新创建活动时都会重复调用获取数据。

水果项目

public class FruitItems implements Parcelable {
    private String fruit_title;
    private String fruit_description;
    private String fruit_image;
    public String getFruit_title() {
        return fruit_title;
    }
    public void setFruit_title(String fruit_title) {
        this.fruit_title = fruit_title;
    }
    public String getFruit_description() {
        return fruit_description;
    }
    public void setFruit_description(String fruit_description) {
        this.fruit_description = fruit_description;
    }
    public String getFruit_image() {
        return fruit_image;
    }
    public void setFruit_image(String fruit_image) {
        this.fruit_image = fruit_image;
    }

    @Override
    public int describeContents() {
        return 0;
    }
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.fruit_title);
        dest.writeString(this.fruit_description);
        dest.writeString(this.fruit_image);
    }
    public FruitItems() {
    }
    protected FruitItems(Parcel in) {
        this.fruit_title = in.readString();
        this.fruit_description = in.readString();
        this.fruit_image = in.readString();
    }
    public static final Parcelable.Creator<FruitItems> CREATOR = new Parcelable.Creator<FruitItems>() {
        @Override
        public FruitItems createFromParcel(Parcel source) {
            return new FruitItems(source);
        }
        @Override
        public FruitItems[] newArray(int size) {
            return new FruitItems[size];
        }
    };
}

主要活动

public class MainActivity extends AppCompatActivity {
    private final String TAG = "MainActivity";
    private final String KEY_POST_ITEMS = "fruititems";
    //List of fruits
    private List<FruitItems> mFruitItemsList;
    //Views
    private RecyclerView recyclerView;
    private RecyclerView.Adapter adapter;
    private ProgressDialog mProgressDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate called");
        //Initializing Views
        recyclerView = (RecyclerView) findViewById(R.id.fruit_recycler);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);

         if (savedInstanceState != null && savedInstanceState.containsKey(KEY_POST_ITEMS)) {
              mFruitItemsList = savedInstanceState.getParcelableArrayList(KEY_POST_ITEMS);
         } else {
              //Initializing the fruitlist
              mFruitItemsList = new ArrayList<>();
              if (NetworkCheck.isAvailableAndConnected(this)) {
              getData();
              } else {
            final Context mContext;
            mContext = this;
            final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
            alertDialogBuilder.setTitle(R.string.alert_titl);
            alertDialogBuilder.setCancelable(false);
            alertDialogBuilder.setIcon(R.mipmap.ic_launcher);
            alertDialogBuilder.setMessage(R.string.alert_mess);
            alertDialogBuilder.setPositiveButton(R.string.alert_retry, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    if (!NetworkCheck.isAvailableAndConnected(mContext)) {
                        alertDialogBuilder.show();
                    } else {
                        getData();
                    }
                }
            });
            alertDialogBuilder.setNegativeButton(R.string.alert_cancel, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    finish();
                }
            });
            alertDialogBuilder.show();

        }
          }
        adapter = new FruitAdapter(mFruitItemsList, this);
        recyclerView.setAdapter(adapter);
    }
    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
           savedInstanceState.putParcelableArrayList(KEY_POST_ITEMS, ArrayList<? extends Parcelable>))mFruitItemsList);
           super.onSaveInstanceState(savedInstanceState);
    }

    //Getting json data
    private void getData(){
        Log.d(TAG, "getData called");
        //Show progress dialog
        mProgressDialog = new ProgressDialog(MainActivity.this);
        mProgressDialog.setCancelable(false);
        mProgressDialog.setMessage(this.getResources().getString(R.string.load_fruit));
        mProgressDialog.show();
        //Creating a json request
        JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(ConfigFruit.GET_URL,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.d(TAG, "onResponse called");
                        //Dismissing the progress dialog
                        if (mProgressDialog != null) {
                            mProgressDialog.hide();
                        }

                        //calling method to parse json array
                        parseData(response);
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                    }
                });
        //Creating request queue
        RequestQueue requestQueue = Volley.newRequestQueue(this);
        //Adding request to the queue
        requestQueue.add(jsonArrayRequest);
    }
    //parsing json data
    private void parseData(JSONArray array){
        Log.d(TAG, "Parsing array");

        for(int i = 0; i<array.length(); i++) {
            FruitItems fruitItem = new FruitItems();
            JSONObject jsonObject = null;
            try {
                jsonObject = array.getJSONObject(i);
                fruitItem.setFruit_title(jsonObject.getString(ConfigFruit.TAG_POST_TITLE));
                fruitItem.setFruit_description(jsonObject.getString(ConfigFruit.TAG_POST_DESCRIPTION));
                //Parsing image
                JSONObject fruitImage = jsonObject.getJSONObject("thumbnail");
                fruitItem.setFruit_image(fruitImage.getString("url"));
            } catch (JSONException w) {
                w.printStackTrace()
            }
            mFruitItemsList.add(fruitItem);
        }
        adapter.notifyItemRangeChanged(0, adapter.getItemCount());
    }
}

我可能不是一个专业人士,但我知道我在上面的代码中犯了错误,否则应该有效。

现在,我的问题是我在哪里犯了错,我该如何弥补这个错误?

编辑

我已经编辑了上面的代码,以反映我接受的答案。它运行良好,但仍然存在问题。

我从主活动开始活动B。如果我在活动B中按下后退按钮,数据将被保存,但当我按下向上按钮时,getData将被再次调用并重新获取数据。

拜托,这附近有没有?

您的主活动中似乎没有onSaveInstanceState。你需要像这样的东西

@Override
protected void onSaveInstanceState (Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putParcelableArrayList(KEY_POST_ITEMS,mFruitItemsList) ;
}

为了保留即将被销毁的活动和正在创建的活动的数据,您需要覆盖onSaveInstance回调

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    savedInstanceState.putParcelableArrayList(KEY_POST_ITEMS, (ArrayList)mFruitItemsList);
    super.onSaveInstanceState(savedInstanceState);
}

注意:永远记得调用超类。

最新更新