sql - Android LoadMore-ListView -
i have internal-database(sqlite) many entries. decided load first 20 entries in listview when user starts activity , when scrolls down can load 20 more each time pressing button if there entries left.
edit
//oncreate() acceptedlogs = helper.getlogsrange(0, load_amount); loadedentriescounter = load_amount; logadapter = new logadapter(acceptedlogs); logrecyclerview.setadapter(logadapter); logrecyclerview.sethasfixedsize(false); linearlayoutmanager = new linearlayoutmanager(getcontext()); logrecyclerview.setlayoutmanager(linearlayoutmanager); @override public void onscrolled(recyclerview recyclerview, int dx, int dy) { super.onscrolled(recyclerview, dx, dy); visibleitemcount = logrecyclerview.getchildcount(); totalitemcount = logrecyclerview.getlayoutmanager().getitemcount(); int firstvisibleitemposition = linearlayoutmanager.findfirstvisibleitemposition(); if (loading) { // boolean set true if loading , false after update adaptor if (totalitemcount > previoustotalcount) { previoustotalcount = totalitemcount; } } if (!loading && (totalitemcount - visibleitemcount) <= (firstvisibleitemposition + visible_threshold)) { loading = true; list<log> newlogs = helper.getlogsrange(loadedentriescounter, load_amount); loadedentriescounter += load_amount; logadapter.logs.addall(newlogs); logadapter.notifydatasetchanged(); } }
the loading happens ones! have set loading on false?
first, better use recyclerview viewholder, second better load data on scroll listener , trick, example have loaded 20 items when scroll list there load data when scroll list , scrolled example 18 item @ bottom, here start async task , when scroll 20 loading finish , update list 20 more user not see when loading.
mvisiblethreshold = 2 // count items bottom of current list when load start.
here on scroll listener recyclerview (can adjusted listview):
mproductsresultslist.setonscrolllistener(new recyclerview.onscrolllistener() { @override public void onscrollstatechanged(recyclerview recyclerview, int newstate) { super.onscrollstatechanged(recyclerview, newstate); } @override public void onscrolled(recyclerview recyclerview, int dx, int dy) { super.onscrolled(recyclerview, dx, dy); mvisibleitemcount = mproductsresultslist.getchildcount(); mtotalitemcount = mproductsresultslayoutmanager.getitemcount(); mfirstvisibleitem = mproductsresultslayoutmanager.findfirstvisibleitemposition(); if (mloadinginprogress) { // boolean set true if loading , false after update adaptor if (mtotalitemcount > mprevioustotal) { mprevioustotal = mtotalitemcount; } } if (!mloadinginprogress && (mtotalitemcount - mvisibleitemcount) <= (mfirstvisibleitem + mvisiblethreshold)) { mloadinginprogress = true; mlastpagerequest++; // current page load , add // here load data , update adapter // if in async task start here , set mloadinginprogress true , onpostexecute add list result , make notifydatasetchanged on adapter mloadinginprogress false. } } });
one more: don't touch views in background tasks (otherwise stuck main thread), make updates , notifications after task code in onpostexecute runonuithread.
okay interested in solution improve answer:
mlastpagerequest - int use know page loaded , must load next it's incrementing each time 1 ++
after loading data (from database or web request should add downloaded items list). in project list "mcategoryproducts" , adapter mproductsresultslistadapter.
all u need add next items downloaded list attached adapter
mcategoryproducts.addall(downloadedlistproducts); // here adding items loaded existing list end,
now next code:
public void displaygotresults(){ if(mcategoryproducts != null){ if(mproductsresultslistadapter == null && mlastpagerequest==1){ mproductsresultslistadapter = new productlistrecyclerviewadapter(this, mcategoryproducts, true); mproductsresultslist.setadapter(mproductsresultslistadapter); mproductsresultslistadapter.setclicklistener(this); }else{ mproductsresultslistadapter.notifydatasetchanged(); //notifyiteminserted(msearchlist.size()-1); } if(mcategoryproducts.size()>0) { mcategoryisemptyinfo.setvisibility(view.gone); }else{ mcategoryisemptyinfo.setvisibility(view.visible); } }else{ mcategoryisemptyinfo.setvisibility(view.visible); } }
here if adapter not initialised create , attaching our list mcategoryproducts otherwise if second loading simple notify adapter "hey man new data comming :)" with:
mproductsresultslistadapter.notifydatasetchanged();
notes: mcategoryisemptyinfo - view show when there no items display.
here custom adaptor interface clicks can handled in activity )
public class productlistrecyclerviewadapter extends recyclerview.adapter<productlistrecyclerviewadapter.productlistrecyclerviewholder> { private layoutinflater minflater; private context mcontext; private drawerlayout mnavigationdrawer; private clicklistener mclicklistener; private longclicklistener mlongclicklistener; list<productmodel> navigationdata = collections.emptylist(); private imageloader mimageloader; private volleyservicesingleton mvollayservice; private boolean mshowthumbnail; //for animations private int mlastpositiion = -1; public productlistrecyclerviewadapter (context context, list<productmodel> navdata, boolean showthumbnail){ minflater = layoutinflater.from(context); this.navigationdata = navdata; mcontext = context; mvollayservice = volleyservicesingleton.getinstance(); mimageloader = mvollayservice.getimageloader(); mshowthumbnail = showthumbnail; } @override public productlistrecyclerviewholder oncreateviewholder(viewgroup parent, int viewtype) { view view = minflater.inflate(r.layout.list_item_product, parent, false); productlistrecyclerviewholder holder = new productlistrecyclerviewholder(view); return holder; } @override public void onbindviewholder(final productlistrecyclerviewholder viewholder, int position) { productmodel currentitem = navigationdata.get(position); viewholder.productbrand.settext(currentitem.manufacturername); viewholder.productname.settext(currentitem.name); viewholder.productcode.settext(currentitem.code); viewholder.productprice.settext(string.format(mcontext.getstring(r.string.money_sign), utils.decimalwithcommas(string.valueof(currentitem.dealerprice)))); if(constants.show_image_thumbnails_in_list && mshowthumbnail){ if(currentitem.catalogimage != null && currentitem.catalogimage.contains("http")){ viewholder.productthumbnail.setvisibility(view.visible); mimageloader.get(currentitem.catalogimage, new imageloader.imagelistener() { @override public void onresponse(imageloader.imagecontainer response, boolean isimmediate) { viewholder.productthumbnail.setimagebitmap(response.getbitmap()); } @override public void onerrorresponse(volleyerror error) { } }); } }else{ viewholder.productthumbnail.setvisibility(view.gone); } } public void setanimation(view viewtoanimate, int position) { // if bound view wasn't displayed on screen, it's animated if (position > mlastpositiion) { animation animation = animationutils.loadanimation(mcontext, android.r.anim.slide_in_left); viewtoanimate.startanimation(animation); mlastpositiion = position; } } @override public int getitemcount() { return navigationdata.size(); } public void setclicklistener(clicklistener clicklistener){ this.mclicklistener = clicklistener; } public void setlongclicklistener(longclicklistener lognclicklistener){ this.mlongclicklistener = lognclicklistener; } public class productlistrecyclerviewholder extends recyclerview.viewholder implements view.onclicklistener, view.onlongclicklistener{ textview productbrand; textview productname; textview productcode; textview productprice; imageview productthumbnail; public productlistrecyclerviewholder(view itemview) { super(itemview); productbrand = (textview) itemview.findviewbyid(r.id.product_brand); productname = (textview) itemview.findviewbyid(r.id.product_name); productcode = (textview) itemview.findviewbyid(r.id.product_code); productprice = (textview) itemview.findviewbyid(r.id.product_price); productthumbnail = (imageview) itemview.findviewbyid(r.id.product_thumbnail); itemview.setonclicklistener(this); itemview.settag(this); itemview.setonlongclicklistener(this); } @override public void onclick(view v) { if(mclicklistener!=null){ mclicklistener.itemclicked(v, getadapterposition()); } } @override public boolean onlongclick(view v) { if(mlongclicklistener!=null){ mlongclicklistener.itemlongclicked(v, getadapterposition()); } return false; } } public interface clicklistener{ void itemclicked(view view, int position); } public interface longclicklistener{ void itemlongclicked(view view, int position); } }
it not work without update needs, nice sample how must )
make attention on
mproductsresultslistadapter.setclicklistener(this);
then in activity can catch clicks :
public class productlistactivity extends actionbaractivity implements productlistrecyclerviewadapter.clicklistener { //..... @override public void itemclicked(view view, int position) { } //..... }
one more thing if need catch click example on specific view in item in list example on image in view holder set click listener "this" , set tag view , in activity can tag view , know clicked :)
your loading database:
loading = true; list<log> newlogs = helper.getlogsrange(loadedentriescounter, load_amount); loadedentriescounter += load_amount; logadapter.logs.addall(newlogs); loading = false; // somewhere here
but not correct way load data can stuck main thread coz if database big or make "heavy" selection can stuck several milisec. must data loading in async tasks , on task done notify adapter.
in project load data webapi, not database in anyway must done in same way via async task, proper way )
class loadnextpagetask extends asynctask<integer, void, list<productmodel>> { int pagetoload; public loadnextpagetask(int pagetoload){ this.pagetoload = pagetoload; } @override protected list<productmodel> doinbackground(integer... params) { return helper.getlogsrange(loadedentriescounter, load_amount); // here apply page load??? not sure } @override protected void onpreexecute() { mmainloadingprogress.setvisibility(view.visible); loading = true; } @override protected void onpostexecute(list<productmodel> newlogs) { loading = false; loadedentriescounter += load_amount; logadapter.logs.addall(newlogs); runonuithread(new runnable() { @override public void run() { logadapter.notifydatasetchanged(); } }); mmainloadingprogress.setvisibility(view.gone); } }
above async task please update needs data loading simple start with:
new loadnextpagetask(pagenumber).execute(); // page int
Comments
Post a Comment