Android recyclerview adding duplicate elements on each activity creation -
when launch new fragment navigation drawer, it's meant take me home page cardview of matching profiles. works great first time , every profile want show there. however, when navigate away fragment , click on again, elements duplicated, , each subsequent time refresh page items duplicated once more. believe problem lies somewhere in recyclerview adapter not clearing on activity create, have't been able pinpoint it. here's fragment class
public class homefragment extends fragment { private customlistadapter listadapter; private static final string profileurl = "http://10.0.2.2:3000/apip/buyers/profiles"; private static final string tag = selectbuyerprofile.class.getsimplename(); private progressdialog pdialog; private listview listview; private list<buyerprofile> buyersprofiles = new arraylist<buyerprofile>(); private view root; //private rvadapter recycleradapter; @override public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) { root = inflater.inflate(r.layout.fragment_home, container, false); return root; } @override public void onactivitycreated(bundle savedinstancestate) { super.onactivitycreated(savedinstancestate); recyclerview rv = (recyclerview) getactivity().findviewbyid(r.id.rv); //rv.additemdecoration(new divideritemdecoration(getactivity(), divideritemdecoration.vertical_list)); rv.sethasfixedsize(true); linearlayoutmanager llm = new linearlayoutmanager(getactivity()); rv.setlayoutmanager(llm); rv.setitemanimator(new defaultitemanimator()); final rvadapter recycleradapter = new rvadapter(buyersprofiles); rv.setadapter(recycleradapter); requestqueue mrequestqueue; cache cache = new diskbasedcache(getactivity().getcachedir(), 1024 * 1024); network network = new basicnetwork(new hurlstack()); mrequestqueue = new requestqueue(cache, network); mrequestqueue.start(); jsonarrayrequest profilerequest = new jsonarrayrequest(profileurl, new response.listener<jsonarray>() { @override public void onresponse(jsonarray response) { // parsing json for(int = 0; < response.length(); i++) { try { jsonobject obj = response.getjsonobject(i); buyerprofile parsedprofile = new buyerprofile(); parsedprofile.setbuyerproftitle(obj.getstring("title")); parsedprofile.setdescription(obj.getstring("description")); parsedprofile.setlocations(obj.getstring("locations")); parsedprofile.setassettypes(obj.getstring("asset_type")); parsedprofile.setpropertystatuses(obj.getstring("property_status")); //parsedprofile.setbuyerid("select"); buyersprofiles.add(parsedprofile); } catch (exception e) { e.printstacktrace(); } } recycleradapter.notifydatasetchanged(); // notifying list adapter data changes // renders list view updated data //hidepdialog(); } }, new response.errorlistener() { @override public void onerrorresponse(volleyerror error) { //toast.maketext(selectbuyerprofile.this,"error",toast.length_long).show(); } }); mrequestqueue.add(profilerequest); } }
and here rvadapter class
public class rvadapter extends recyclerview.adapter<rvadapter.personviewholder> { private activity activity; private layoutinflater inflater; private list<buyerprofile> profileitems; private static boolean itemfavorited; rvadapter(list<buyerprofile> profiles) { this.profileitems = profiles; } public static class personviewholder extends recyclerview.viewholder { textview name; textview description; textview locations; textview id; textview investmentrangemin; textview investmentrangemax; textview assettypes; textview propertystatuses; imageview favoritebutton; cardview cardview; personviewholder(view itemview) { super(itemview); name = (textview) itemview.findviewbyid(r.id.titletext); description = (textview) itemview.findviewbyid(r.id.descriptiontext); investmentrangemin = (textview) itemview.findviewbyid(r.id.investmentrangemin); investmentrangemax = (textview) itemview.findviewbyid(r.id.investmentrangemax); locations = (textview) itemview.findviewbyid(r.id.locations); id = (textview) itemview.findviewbyid(r.id.profilenumber); assettypes = (textview) itemview.findviewbyid(r.id.assettypes); propertystatuses = (textview) itemview.findviewbyid(r.id.propertystatuses); favoritebutton = (imageview) itemview.findviewbyid(r.id.favorite_select); cardview = (cardview) itemview.findviewbyid(r.id.cv); //user selects favorite on matched profile itemfavorited = false; favoritebutton.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { if(!itemfavorited) { favoritebutton.setimageresource(r.drawable.ic_favorite); //cardview.setcardbackgroundcolor(r.color.colorprimary); itemfavorited = true; } else { favoritebutton.setimageresource(r.drawable.ic_favorite_border); itemfavorited = false; } } }); } } @override public int getitemcount() { return profileitems.size(); } @override public personviewholder oncreateviewholder(viewgroup viewgroup, int i) { view v = layoutinflater.from(viewgroup.getcontext()).inflate(r.layout.item, viewgroup, false); personviewholder pvh = new personviewholder(v); return pvh; } @override public void onbindviewholder(personviewholder personviewholder, int i) { personviewholder.name.settext(profileitems.get(i).getbuyerproftitle()); personviewholder.description.settext(profileitems.get(i).getdescription()); personviewholder.locations.settext(profileitems.get(i).getlocations()); personviewholder.assettypes.settext(profileitems.get(i).getassettypes()); personviewholder.propertystatuses.settext(profileitems.get(i).getpropertystatuses()); } @override public void onattachedtorecyclerview(recyclerview recyclerview) { super.onattachedtorecyclerview(recyclerview); } /* @override public object getitem(int location) { return profileitems.get(location); } */ @override public long getitemid(int position) { return position; } }
finally here fragments xml
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:padding="0dp" > <relativelayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="8dp" > <textview android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="matches" android:layout_alignparenttop="true" android:layout_alignparentend="false" android:id="@+id/matchestext" android:textalignment="center" android:textsize="20dp" android:textcolor="@color/navigationbarcolor" android:layout_alignparentstart="false" android:layout_alignparentbottom="false" android:layout_alignparentleft="false" android:layout_alignparentright="true"/> <android.support.v7.widget.recyclerview android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/rv" android:layout_below="@id/matchestext" /> <!-- thumbnail image --> <imageview android:id="@+id/imgbillionaire" android:src="@drawable/ic_perm_identity" android:layout_width="80dp" android:layout_height="80dp" android:layout_alignparentleft="true" android:layout_marginright="8dp" android:layout_alignparentend="false" android:layout_alignparentstart="true" android:nestedscrollingenabled="false" android:visibility="invisible"/> <!-- name of asset --> <textview android:id="@+id/titletext" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_aligntop="@+id/imgbillionaire" android:layout_torightof="@+id/imgbillionaire" android:textsize="@dimen/title" android:textstyle="bold" /> <!-- description --> <textview android:id="@+id/descriptiontext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@id/titletext" android:layout_margintop="1dip" android:layout_torightof="@+id/imgbillionaire" android:textsize="@dimen/description" /> <!-- source --> <textview android:id="@+id/locations" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@id/descriptiontext" android:layout_margintop="5dp" android:layout_torightof="@+id/imgbillionaire" android:textcolor="@color/wealthsource" android:textsize="@dimen/investmentrange" /> <!-- source --> <textview android:id="@+id/assettypes" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@id/locations" android:layout_margintop="5dp" android:layout_torightof="@+id/imgbillionaire" android:textcolor="@color/wealthsource" android:textsize="@dimen/investmentrange" /> <!-- source --> <textview android:id="@+id/propertystatuses" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@id/assettypes" android:layout_margintop="5dp" android:layout_torightof="@+id/imgbillionaire" android:textcolor="@color/wealthsource" android:textsize="@dimen/investmentrange" /> <!-- year --> <textview android:id="@+id/profilenumber" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentbottom="false" android:layout_alignparentright="true" android:textcolor="@color/year" android:textsize="@dimen/date" /> </relativelayout> </linearlayout>
any ideas why items in recyclerview keep duplicating on each page refresh?
what can possibly happening each time network request returns, tries add every new item existing list inside fragment.
depending on how implement navigation logic, fragment won't destroyed system once navigate away it, instead calling series of lifecycle callbacks:
onpause() -> onstop() -> ondestroyview()
and when return fragment, required lifecycle callbacks called until reaches active state.
oncreateview() -> onactivitycreated() -> onstart() -> onresume()
more information on fragment's lifecycle works can found here: https://developer.android.com/guide/components/fragments.html
since fragment not getting destroyed , recreated, buyersprofiles
reference may hold previous data when return. since network call not overwriting original list, append new data fetched network next existing data each time calls it's onresponse
callback.
this may affect use cases implement kind of pull-to-refresh logic or refresh button, new network call not clean list.
one thing try avoid repetition adding
buyersprofiles = new arraylist<buyerprofile>();
to top of onresponse()
callback.
hope helps.
Comments
Post a Comment