I am fetching data from json with Volley and populating RecyclerView with the parsed data but I ran into a bit of problem:
The call to get the items is in onCreate
method, so the call is repeated each time the activity is recreated both from configuration changes and otherwise; hence the data is reloaded. So I found this answer that uses parcelables
and this article on Codepath (still on parcelables). After I have followed the instructions explicitly (or so I feel), there seems to be no change: the call to get data is repeated each time the activity is recreated.
FruitItems
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];
}
};
}
MainActivity
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());
}
}
I may not be a pro but I know that I have goofed somewhere in the codes above, else it should have worked.
Now, my question is where did I goof and how do I plug this mistake?
EDIT
I have edited the codes above to reflect the answer that I accepted. It works fine but there is still a problem.
I start Activity B from MainActivity. If I press the back-button in Activity B the data is saved but when I press the up-button, the getData
is called again and the data is re-fetched.
Please, is there anyway around this?
In order to retain your data for the activity that is about to be destructed and the one that is being created, you need to override the onSaveInstance
callback
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putParcelableArrayList(KEY_POST_ITEMS, (ArrayList)mFruitItemsList);
super.onSaveInstanceState(savedInstanceState);
}
NOTE: always remember to call the superclass.