java - How to access the data source of a RecyclerView adapter's ViewHolder? -


the constructor of recyclerview's adapter looks like:

context context; list<connectionitem> connections;  public connectionslistadapter(context context, list connections) {     this.context = context;     this.connections = connections; } 

after adapter's declarations, declare static viewholder class recyclerview, handles onclicks of buttons:

public static class viewholder extends recyclerview.viewholder implements view.onclicklistener {      public context context;      public imageview connectionimage;     public textview connectionname;     public imagebutton startmsg;      public viewholder(view itemview, list<connectionitem> connections) {         super(itemview);         ...         startmsg.setonclicklistener(this);     }      @override     public void onclick(view v) {         intent intent = new intent(v.getcontext(), chatactivity.class);         intent.putextra("name", connections.get(getadapterposition()).getname()); // error because accessing static context         intent.putextra("id", connections.get(getadapterposition()).getuid()); // error because accessing static context         context.startactivity(intent);     } } 

the problem connections not accessible static context in viewholder static class. what's best way viewholder information recyclerview adapter? workaround, passing data source constructor of viewholder , having new instance variable in viewholder data source:

public static class viewholder extends recyclerview.viewholder implements view.onclicklistener {     public context context;     public list<connectionitem> connections;      public imageview connectionimage;     public textview connectionname;     public imagebutton startmsg;  public viewholder(view itemview, list<connectionitem> connections) {         super(itemview);         this.connections = connections;         ...         startmsg.setonclicklistener(this); }      @override     public void onclick(view v) {         intent intent = new intent(v.getcontext(), chatactivity.class);         intent.putextra("name", connections.get(getadapterposition()).getname()); // okay         intent.putextra("id", connections.get(getadapterposition()).getuid()); // okay         context.startactivity(intent);     } 

does way @ break viewholder pattern or create other problems in future?

your responsibilities/concerns little scrambled.

in mvc terms, viewholder view. it's object has references subviews findviewbyid() doesn't have called on , over. it's still view.

however, have constructor model data argument, , has bad smell it.

  • the properties/variables viewholder should have views.

  • the thing viewholder constructor should ever calling findviewbyid()

you haven't talked adapter much, you'll notice override 2 methods: oncreateviewholder , onbindviewholder.

within oncreateviewholder construct viewholder that's applicable view type. that's it. may have inflate different layouts depending on view type, dealing views here. don't pass model data viewholder in constructor.

within onbindviewholder, here hook view model data.

something define bind() method viewholder it's clear model data being handed off. bind() method takes data , calls settext , similar methods make views reflect model data adapter position.

but come ugly part of recyclerview's adapter design. there no onitemclicklistener adapter.

google argues better design; events should handled list item view anyway. that. problem event has meet model data, , it's adapter has model data, not list item view.

and google has emphasized can't use final on values position; need call getadapterposition() in order index model data.

so have gone pattern accommodates these constraints.

  • i define interface event listener method takes position argument.

  • i create instance of listener in adapter

  • every time bind viewholder pass listener instance (so viewholder have reference listener, not adapter)

  • on event handler in viewholder, call getadapterposition() position of list item, call listener method position

  • the adapter gets listener callback, accesses correct model data , performs desired action

so here's example: have list of items have been selected, i.e. products in online shopping cart have remove button big x. have handle remove button.

define interface:

    interface onitemremovedlistener {          void itemremoved(int position);     } 

create instance of listener in adapter

    private onitemremovedlistener mcallback; 

set in adapter constructor:

    mcallback = new onitemremovedlistener() {         @override         public void itemremoved(int position) {             mitemlist.remove(position);             notifydatasetchanged();         }     }; 

the viewholder subclass:

public static class productitemviewholder extends recyclerview.viewholder {      private textview mproductname;      private button mremovebutton;      private onitemremovedlistener mlistener;      public productitemviewholder(view itemview) {         super(itemview);         mproductname = (textview) itemview.findviewbyid(r.id.product_name);         mremovebutton = (button) itemview.findviewbyid(r.id.remove_button);     }      public void bind(model data, onitemremovedlistener listener) {          mproductname.settext(data.getproductname());         mlistener = listener;         mremovebutton.setonclicklistener(new onclicklistener() {              @override             public void onclick(view view) {                 int position = getadapterposition();                 if (position >= 0) {                     mlistener.itemremoved(position);                 }             }         });     } } 

then onbindviewholder override looks this:

    @override     public void onbindviewholder(productitemviewholder holder, int position) {          holder.bind(mitemlist.get(position), mcallback);     } 

Comments

Popular posts from this blog

jOOQ update returning clause with Oracle -

java - Warning equals/hashCode on @Data annotation lombok with inheritance -

java - BasicPathUsageException: Cannot join to attribute of basic type -