Reputation: 601
I'm in the middel of making an app, that takes some data via a volley request, and sets the data in a ListView on a ListFragment.
My problem is that when I use my back-button to transition back to the previous activity and out of the app, (onStop), when I reopen the app from the appdrawer and go to the ListFragment, the list it shows is duplicated.
Refere pictures below:
The code:
The ListFragment class:
package lassebjoerklund.easyfridge;
import android.app.Activity;
import android.app.Fragment;
import android.app.ListFragment;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
/**
* Created by lassebjorklund on 17/02/16.
*/
public class ProductsList extends ListFragment {
ProductListListnerInteface productListListnerInteface;
public interface ProductListListnerInteface {
public void onProductSelected(int pos);
}
@Override
public void onCreate(Bundle savedInstanceState) {
Log.d(getActivity().getClass().getSimpleName(), "onCreate");
super.onCreate(savedInstanceState);
if(savedInstanceState == null) {
setListAdapter(new ProductAdapter(getActivity(), BootActivity.getProductsToDisplayInlist()));
}else{
}
}
@Override
public void onAttach(Context context) {
Log.d(getActivity().getClass().getSimpleName(), "onAttach");
super.onAttach(context);
try {
productListListnerInteface = (ProductListListnerInteface) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + "must implement ProductListListnerInteface");
}
}
@Override
public void onStart() {
Log.d(getActivity().getClass().getSimpleName(), "onStart");
super.onStart();
if (getFragmentManager().findFragmentById(R.id.fragment_container_list) != null) {
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
}
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
productListListnerInteface.onProductSelected(position);
}
}
The Activity the binds the ListFragment with the DetailFragment (Not a part of the problem I guss)
package lassebjoerklund.easyfridge;
import android.app.Activity;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.KeyEvent;
/**
* Created by lassebjorklund on 17/02/16.
*/
public class ProductViewController extends FragmentActivity implements ProductsList.ProductListListnerInteface {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.products_list_layout);
if (findViewById(R.id.fragment_container_list) != null) {
if (savedInstanceState != null) {
return;
}
ProductsList productsList = new ProductsList();
productsList.setArguments(getIntent().getExtras());
getFragmentManager().beginTransaction().add(R.id.fragment_container_list, productsList).commit();
}
}
@Override
public void onProductSelected(int pos) {
ProductDetail productDetail = (ProductDetail) getFragmentManager().findFragmentById(R.id.details_fragment_container);
if (productDetail != null) {
productDetail.updateProductOnPos(pos);
} else {
ProductDetail newProductDetail = new ProductDetail();
Bundle args = new Bundle();
args.putInt("Position", pos);
newProductDetail.setArguments(args);
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container_list, newProductDetail);
fragmentTransaction.addToBackStack("ProductList");
fragmentTransaction.commit();
}
}
}
The launcher activity
package lassebjoerklund.easyfridge;
import android.app.Activity;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
public class BootActivity extends Activity {
private static ArrayList<Products> productsToDisplayInlist = new ArrayList<>();
private String TAG = BootActivity.class.getSimpleName();
private String url = "XXXXXXXXXXXXXXXXXXXX";
private String jsonRespons = "";
private RequestQueue rQueue;
@Override
protected void onCreate(Bundle savedInstanceState) {
//Layout
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_boot_layout);
//Custom Adapter for list view, for ref.
//final ProductAdapter adapter = new ProductAdapter(this, productsToDisplayInlist);
//RequestQueue
rQueue = Volley.newRequestQueue(this);
//Methode to populate Arralist
//Intent to switch to activity
final Intent dispalyProductsIntent = new Intent(BootActivity.this, ProductViewController.class);
getRequest();
final ImageButton updateViewButton = (ImageButton) findViewById(R.id.bViewProducts);
updateViewButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startActivity(dispalyProductsIntent);
}
});
}
public void getRequest() {
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, url, null, new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
try {
for (int i = 0; i < response.length(); i++) {
JSONObject productToBuild = (JSONObject) response.get(i);
String name = productToBuild.getString("name");
String type = productToBuild.getString("type");
int id = productToBuild.optInt("id");
String removalDate = productToBuild.getString("removal_date");
String placementDate = productToBuild.getString("placement_date");
Products product = new Products(name, placementDate, removalDate, type);
productsToDisplayInlist.add(product);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("Volly", "Error");
error.printStackTrace();
}
});
rQueue.add(jsonArrayRequest);
}
public void postRequest() {
}
public static ArrayList<Products> getProductsToDisplayInlist() {
return productsToDisplayInlist;
}
@Override
protected void onResume() {
Log.d("onResume", "onResume");
/*Toast toast = Toast.makeText(this, "onResume", Toast.LENGTH_LONG);
toast.show();*/
super.onResume();
}
@Override
protected void onRestart() {
Log.d("onRestart", "onRestart");
/*Toast toast = Toast.makeText(this, "onRestart", Toast.LENGTH_SHORT);
toast.show();*/
super.onRestart();
}
@Override
protected void onStop() {
Log.d("onStop", "onStop");
// productsToDisplayInlist.clear();
super.onStop();
}
@Override
protected void onPause() {
Log.d("onPause", "onPause");
super.onPause();
}
}
I can't seem to find the problem.. Can anyone help ?
Upvotes: 0
Views: 53
Reputation: 11903
productsToDisplayInlist
is static and will not be recreated each time you go back to the BootActivity
until your application itself is recreated.
When you receive the response you are only ever adding to the collection so every time the response is received you are adding duplicates.
There are many ways to fix this easiest of which is to just add productsToDisplayInlist.clear()
to the beginning of onResponse()
since the list is being totally repopulated anyways.
Upvotes: 2
Reputation: 536
I think the problem is that in BootActivity, you are not clearing productsToDisplayInList (productsToDisplay.clear();
) before you add the products in the HTTP response to it. productsToDisplayInList is static, which means it holds its state throughout the app's lifetime. I'm not 100% sure about this, but it could be that it still contains the data whenever you leave the bottom activity in the stack (exiting the app) because the app is still running in the background.
Upvotes: 0