ListView Fragment

1

The list is loaded into the Fragment by selecting the ActionBar menu item. However, when I click on a tab other than Fragment with the list, and return to the tab with the list, the list that was previously is not destroyed. That is, a new request is made to the API, they return the data normally and they are added to the list that was already there.

How do I fix this?

My Fragment :

public class Fragment1 extends ListFragment {
    List<Notice> result = new ArrayList<Notice>();
    NoticeAdapter adpt;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        View view = inflater.inflate(R.layout.list_notice, container, false);
        ListView lView = (ListView) view.findViewById(android.R.id.list);

        JsonArrayRequest jReq = new JsonArrayRequest("http://192.168.1.101:3000/notices",
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {

                        for (int i = 0; i < response.length(); i++) {
                                try {
                                    Notice notice = new Notice();
                                notice.setId(response.getJSONObject(i).getInt("id"));
                                notice.setPicture(response.getJSONObject(i).getString("picture"));
                                    notice.setPublicationTime(response.getJSONObject(i).getString("publication_time"));
                                notice.setReducedDescription(response.getJSONObject(i).getString("reduced_description"));
                                notice.setReference(response.getJSONObject(i).getString("reference"));
                                notice.setTitle(response.getJSONObject(i).getString("title"));
                                result.add(notice);
                            } catch (JSONException e) {
                                Toast.makeText(getActivity(), "Falha com a conexão de internet", Toast.LENGTH_LONG).show();
                            }
                        }
                        adpt.setItemList(result);
                        adpt.notifyDataSetChanged();
                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                    }
                });
          Volley.newRequestQueue(getActivity().getApplicationContext()).add(jReq);
        adpt = new NoticeAdapter(result, this.getActivity());
        lView.setAdapter(adpt); 

        return view;
    }
}

And Adapter :

public class NoticeAdapter extends BaseAdapter {

private List<Notice> itemList;
private LayoutInflater inflater;

public NoticeAdapter(List<Notice> itemList, Context ctx) {
    this.itemList = itemList;
    inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

public int getCount() {
    if (itemList != null)
        return itemList.size();
    return 0;
}

public Notice getItem(int position) {
    if (itemList != null)
        return itemList.get(position);
    return null;
}

public long getItemId(int position) {
    if (itemList != null)
        return itemList.get(position).hashCode();
    return 0;
}

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

    if(view == null) {
        view = inflater.inflate(R.layout.item_layout, null);
        holder = new ViewHolder();
        view.setTag(holder);

        holder.tvId = (TextView) view.findViewById(R.id.title);
        holder.tvDesc = (TextView) view.findViewById(R.id.description);
        holder.tvPtime = (TextView) view.findViewById(R.id.publication_time);
    } else {
        holder = (ViewHolder) view.getTag();
    }

    holder.tvId.setText(itemList.get(position).getTitle());
    holder.tvDesc.setText(itemList.get(position).getReducedDescription());
    holder.tvPtime.setText(itemList.get(position).getPublicationTime());

    return view;
}

private static class ViewHolder {
    TextView tvId;
    TextView tvDesc;
    TextView tvPtime;
}

public List<Notice> getItemList() {
    return itemList;
}

public void setItemList(List<Notice> itemList) {
    this.itemList = itemList;
}

}
    
asked by anonymous 29.05.2015 / 11:58

1 answer

1

One of the most important things we should understand when using Fragments is life cycle .

The onCreateView() method is called whenever Fragment needs to be displayed on the screen. As you have the list fill in this method, every time you change tab the method is called and your list receives new items.

This code must be changed to a method that is called only once. The best candidate is onCreate()

Change your code to:

public class Fragment1 extends ListFragment {
    List<Notice> result = new ArrayList<Notice>();
    NoticeAdapter adpt;
    Context context;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        //Obtém e guarda o context para uso futuro
        context = activity;
    }

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

        //Defina aqui o seu request
        JsonArrayRequest jReq = new JsonArrayRequest("http://192.168.1.101:3000/notices",
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {

                        for (int i = 0; i < response.length(); i++) {
                                try {
                                    Notice notice = new Notice();
                                notice.setId(response.getJSONObject(i).getInt("id"));
                                notice.setPicture(response.getJSONObject(i).getString("picture"));
                                    notice.setPublicationTime(response.getJSONObject(i).getString("publication_time"));
                                notice.setReducedDescription(response.getJSONObject(i).getString("reduced_description"));
                                notice.setReference(response.getJSONObject(i).getString("reference"));
                                notice.setTitle(response.getJSONObject(i).getString("title"));
                                result.add(notice);
                            } catch (JSONException e) {
                                Toast.makeText(context, "Falha com a conexão de internet", Toast.LENGTH_LONG).show();
                            }
                        }
                        adpt.setItemList(result);
                        adpt.notifyDataSetChanged();
                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                    }
           });
        adpt = new NoticeAdapter(result, context);
        Volley.newRequestQueue(context.getApplicationContext()).add(jReq);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        View view = inflater.inflate(R.layout.list_notice, container, false);
        ListView lView = (ListView) view.findViewById(android.R.id.list);
        return view;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        setListAdapter(adpt); 
    }
}

Edit

This solution only works if instead of replace you use hide / show to toggle between Fragments .

Another solution is to declare a constructor for the Fragment1 class and place the requesting code there.
Bad idea, there are times when Android needs to create new instances by using the constructor default

Another solution is to test if the result list is empty and only make the request in this case:

public class Fragment1 extends ListFragment {
    List<Notice> result = new ArrayList<Notice>();
    NoticeAdapter adpt;
    Context context;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        //Obtém e guarda o context para uso futuro
        context = activity;
    }

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

        //Defina aqui o seu request
        JsonArrayRequest jReq = new JsonArrayRequest("http://192.168.1.101:3000/notices",
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {

                        for (int i = 0; i < response.length(); i++) {
                                try {
                                    Notice notice = new Notice();
                                notice.setId(response.getJSONObject(i).getInt("id"));
                                notice.setPicture(response.getJSONObject(i).getString("picture"));
                                    notice.setPublicationTime(response.getJSONObject(i).getString("publication_time"));
                                notice.setReducedDescription(response.getJSONObject(i).getString("reduced_description"));
                                notice.setReference(response.getJSONObject(i).getString("reference"));
                                notice.setTitle(response.getJSONObject(i).getString("title"));
                                result.add(notice);
                            } catch (JSONException e) {
                                Toast.makeText(context, "Falha com a conexão de internet", Toast.LENGTH_LONG).show();
                            }
                        }
                        adpt.setItemList(result);
                        adpt.notifyDataSetChanged();
                    }
                }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                    }
           });
        adpt = new NoticeAdapter(result, context);
        setListAdapter(adpt);

        //Se result é está vazia faz a requisição
        if(result.isEmpty){
            Volley.newRequestQueue(context.getApplicationContext())
                  .add(jReq);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        View view = inflater.inflate(R.layout.list_notice, container, false);
        ListView lView = (ListView) view.findViewById(android.R.id.list);
        return view;
    }
}
    
29.05.2015 / 12:30