Listview Fragment

Asked

Viewed 231 times

1

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

How to fix this?

Man 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;
}

}

1 answer

1


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

The method onCreateView() is called whenever the 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 has to be changed to a method that is called only once. The best candidate is the 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 switch between Fragments.

Another solution is to declare a constructor for the class Fragment1 and put there the code that makes the request.
Bad idea, there are times when the Android needs create new instances using the constructor for this purpose default

Another solution will be to test the list result is empty and only make the request in that 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;
    }
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.