android - RecyclerView not updating after adding when data was empty -


i'm facing strange problem when using recylerview inside linearlayout inside cardview. works when initial data i'm passing adapter/recyclerview not empty. when try add item dynamically (when initial data empty), adapter set's items, call's notifydatasetchanged, recyclerview stays empty.

if add data dynamically, when initial collection not empty, works perfectly. it's working on other views well. idea problem be?

thanks in advance!

the xml file:

<layout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:tools="http://schemas.android.com/tools"     xmlns:card_view="http://schemas.android.com/apk/res-auto"     xmlns:app="http://schemas.android.com/apk/res-auto">     <data>     </data>      <linearlayout         android:id="@+id/main_content"         android:layout_width="match_parent"         android:layout_height="match_parent"         android:orientation="vertical">           <android.support.v7.widget.toolbar             android:id="@+id/toolbarcomposer"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:background="@color/colorprimary"             android:elevation="4dp"             app:title="@string/title_timeline"             app:titletextcolor="@color/white"             app:navigationicon="@drawable/ic_arrow_back_black_24dp"             >          </android.support.v7.widget.toolbar>           <android.support.v4.widget.swiperefreshlayout             android:id="@+id/refreshlayout"             android:layout_width="match_parent"             android:layout_height="match_parent"             android:background="@color/intercomsdk_white">              <scrollview                 android:id="@+id/scrollview"                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:padding="7dp"                 android:background="#e1e2e4">                  <linearlayout                     android:layout_width="match_parent"                     android:layout_height="match_parent"                     android:orientation="vertical">                      <include android:id="@+id/messagecardview" layout="@layout/item_timeline_message"/>                      <android.support.v7.widget.cardview                         android:layout_width="match_parent"                         android:layout_height="match_parent"                         card_view:cardelevation="3sp"                         card_view:cardusecompatpadding="true"                         android:layout_margintop="-10dp">                          <linearlayout                             android:layout_width="match_parent"                             android:layout_height="match_parent"                             android:orientation="vertical">                              <android.support.v7.widget.recyclerview                                 android:id="@+id/commentrecyclerview"                                 android:layout_width="match_parent"                                 android:layout_height="0dp"                                 android:background="#e1e2e4"                                 tools:listitem="@layout/item_timeline_comment"                                 android:layout_above="@+id/commentcontainer"                                 android:minheight="10dp"                                 android:layout_weight="1"                                 />                              <linearlayout                                 android:id="@+id/commentcontainer"                                 android:layout_width="match_parent"                                 android:layout_height="wrap_content"                                 android:orientation="horizontal"                                 android:background="@color/chatwhite">                                  <edittext                                     android:id="@+id/commenttextfield"                                     android:layout_width="0dp"                                     android:layout_height="wrap_content"                                     android:textcolorhint="@color/chattextgray"                                     android:textsize="14dp"                                     android:layout_margintop="10dp"                                     android:layout_marginleft="10dp"                                     android:paddingbottom="15dp"                                     android:layout_weight="0.8"                                     android:hint="@string/commentinputhint" />                                  <imagebutton                                     android:id="@+id/sendbutton"                                     android:layout_width="wrap_content"                                     android:layout_height="wrap_content"                                     android:text="verstuur"                                     android:src="@drawable/ic_send_button"                                     android:layout_gravity="center"                                     android:layout_marginright="5dp"                                     android:tint="@color/chatsendbuttontint"                                     android:background="@color/chatwhite"                                     />                              </linearlayout>                          </linearlayout>                     </android.support.v7.widget.cardview>                  </linearlayout>              </scrollview>          </android.support.v4.widget.swiperefreshlayout>      </linearlayout> </layout> 

the activity:

public class timelinemessageactivity extends baseactivity implements timelinemessagepresenter.viewinterface {      private timelinemessagepresenter presenter;     private timelinecommentadapter adapter;      private timelinedatamanager timelinedatamanager;     private networkclientinterface timelinenetworkclient;     private usersettingsstoreinterface usersettingsstore;      private fragmenttimelinemessagebinding binding;     private menu menu;     public int messageid;      private list<timelinecommentmodel> comments = new arraylist<>();      @override     public void oncreate(bundle savedinstancestate) {         super.oncreate(savedinstancestate);          this.usersettingsstore = new usersettingsstore(getmodel().getenvironment());         this.timelinenetworkclient = new networkclient(getmodel().getenvironment(), getmodel().getcredentialstore());         this.timelinedatamanager = new timelinedatamanager(getmodel().gettimelinestore(), timelinenetworkclient);          binding = databindingutil.setcontentview(this, r.layout.fragment_timeline_message);          adapter = new timelinecommentadapter(new timelinecommentadapter.listener() {             @override             public void didclickprofileimage(timelinecommentmodel item) {              }              @override             public void didclickmention(int userid) {                 presenter.didclickmention(userid);             }         }, getmodel());          slideinbottomanimatoradapter animatoradapter = new slideinbottomanimatoradapter(adapter, binding.commentrecyclerview);         binding.commentrecyclerview.setitemanimator(new slideinoutleftitemanimator(binding.commentrecyclerview));         binding.commentrecyclerview.additemdecoration(new divideritemdecoration(this, divideritemdecoration.vertical_list));          binding.commentrecyclerview.setadapter(animatoradapter);         binding.commentrecyclerview.setlayoutmanager(new linearlayoutmanager(this));          binding.refreshlayout.setonrefreshlistener(() -> presenter.refreshmessage());         binding.refreshlayout.setrefreshing(true);          presenter = new timelinemessagepresenter(getmodel(), getrouter(), this.timelinedatamanager);         if(getintent().getintextra("message_id", 0) > 0){             presenter.setmessageid(getintent().getintextra("message_id", 0));         }     }      @override     public void ondestroy() {         presenter = null;         super.ondestroy();     }      @override     public void onstart() {         super.onstart();         presenter.attachview(this);         presenter.refreshmessage();     }      @override     public void onstop() {         presenter.detachview();          view view = this.getcurrentfocus();         if (view != null) {             inputmethodmanager imm = (inputmethodmanager)this.getsystemservice(context.input_method_service);             imm.hidesoftinputfromwindow(view.getwindowtoken(), 0);         }          super.onstop();     }      @override     public void setcomments(list<timelinecommentmodel> items) {          for(timelinecommentmodel model : items) {             this.comments.add(model);         }          adapter.setitems(this.comments);         binding.refreshlayout.setrefreshing(false);     }      @override     public boolean onoptionsitemselected(menuitem item) {         switch (item.getitemid()) {             default:                 return super.onoptionsitemselected(item);         }     }      @override     public void settitle(int title){         this.getsupportactionbar().settitle(this.getstring(title));     }      @override     public void setedittext(string text) {         binding.commenttextfield.settext(text);     }      @override     public void setbuttonenabled(boolean enabled) {         binding.sendbutton.setenabled(enabled);         binding.sendbutton.setalpha((float) (enabled ? 1.0 : 0.5));     }      @override     public void didsendcomment() {         binding.commenttextfield.settext("");         presenter.refreshmessage();     }      public void setmessageid(int messageid){         this.messageid = messageid;     }      public void didclickmention(int userid){         getrouter().openuri(uri.parse("flexappeal://users/"+userid));     }      public void didclickdeletebutton(int id){         alertdialog.builder dialog = new alertdialog.builder(this);         dialog.setmessage(getstring(r.string.confirm_delete_message));         dialog.setnegativebutton(r.string.no, (dialoginterface, i) -> {             dialoginterface.dismiss();         });         dialog.setpositivebutton(r.string.yes, (dialoginterface, i) -> {             presenter.didclickdeletebutton(id);         });         dialog.show();     }      @override     public void didclickbackbutton(){         this.finish();     } } 

the presenter:

public class timelinemessagepresenter extends basepresenter<timelinemessagepresenter.viewinterface> {      interface viewinterface extends basepresenter.viewinterface {         void setcomments(list<timelinecommentmodel> items);          void settitle(int title);         void didsendcomment();          void setbuttonenabled(boolean enabled);         void setedittext(string text);          void didclickbackbutton();     }      private timelineviewmodel message = new timelineviewmodel();     private list<timelinecommentmodel> comments = new arraylist<>();     private string commentmessage;      private int messageid;      @nonnull private final timelinedatamanager datamanager;      private final boolean needsrefresh = true;      public timelinemessagepresenter(@nonnull model model, @nonnull routerinterface router, @nonnull timelinedatamanager datamanager) {         super(model, router);         this.datamanager = datamanager;     }      @override     protected void onattachview() {         super.onattachview();          getmodel().geteventbus().register(this);          updateview();     }      @override     protected void ondetachview() {         getmodel().geteventbus().unregister(this);          super.ondetachview();     }      @subscribe     public void onevent(socketevent event) {         // todo: handle new comment in message event integrate realtime timeline     }      public void updateview() {         if (getview() != null) {             getview().setedittext(commentmessage);             getview().setcomments(comments);         }     }      private boolean shouldenablebutton() {         return (commentmessage != null && commentmessage.length() > 0);     }      public void didclickhighfivebutton(){         datamanager.postlike(messageid).subscribe(message -> {             refreshmessage();         }, error -> {             log.w("timelinepresenter", error);         });     }      public void didclicksendcommentbutton(){         this.datamanager.postcomment(messageid, commentmessage).subscribe(result -> {             getview().didsendcomment();         }, error -> {             log.w("timelinepresenter", error);         });     }      public void refreshmessage() {         datamanager.getmessagedetail(messageid).subscribe(messagedetail ->{             this.comments.clear();              this.message = createviewmodelfortimelinemessage(messagedetail);             if(messagedetail.getcomments() != null){                 for(comments comment : messagedetail.getcomments()) {                     this.comments.add(createviewmodelfortimelinecomment(comment));                 }             }             updateview();         }, error -> {             log.w("timelinemessagepresenter", error);         });      }      private timelinecommentmodel createviewmodelfortimelinecomment(comments c) {         timelinecommentmodel vm = new timelinecommentmodel();         vm.commentid = c.getid();         vm.createdby = c.getuser();         vm.createdat = c.getcreated_at_diff();         vm.message = c.getmessage();          return vm;     }      public void didchangemessage(charsequence message) {         this.commentmessage = message.tostring();          if (getview() != null) {             getview().setbuttonenabled(shouldenablebutton());         }     }      public void setmessageid(int messageid){         this.messageid = messageid;     }      public void didclickmention(int userid){         getrouter().openuri(uri.parse("flexappeal://users/"+userid));     }      public void didclickdeletebutton(int id){         datamanager.deletemessage(id).subscribe(aboolean -> {             getview().didclickbackbutton();         }, error -> {             getview().didclickbackbutton();         });     } } 

the adapter:

class timelinecommentadapter extends bindingrecyclerviewadapter<timelinecommentmodel, itemtimelinecommentbinding> {      private final listener listener;     private final model model;      public timelinecommentadapter(listener listener, model model) {         super(r.layout.item_timeline_comment);         this.listener = listener;         this.model = model;     }      public interface listener {         void didclickprofileimage(timelinecommentmodel item);         void didclickmention(int userid);     }      @override     protected void bind(itemtimelinecommentbinding binding, timelinecommentmodel item, int position) {          picasso.with(binding.getroot().getcontext()).load(item.createdby.getprofileimage()).into(binding.userprofileimage);         binding.userprofileimage.setonclicklistener(view -> listener.didclickprofileimage(item));          binding.userfullname.settext(item.createdby.getfullname());         binding.ago.settext(item.createdat);      }      @override     protected void recycle(itemtimelinecommentbinding binding) {         picasso.with(binding.getroot().getcontext()).cancelrequest(binding.userprofileimage);     } } 

the bindingrecyclerviewadapter:

public abstract class bindingrecyclerviewadapter<t, b extends viewdatabinding>         extends recyclerview.adapter<bindingrecyclerviewadapter<t, b>.viewholder> {      public class viewholder extends recyclerview.viewholder implements view.onclicklistener {         public final b binding;          public viewholder(b binding) {             super(binding.getroot());             this.binding = binding;             this.itemview.setonclicklistener(this);         }          @override         public void onclick(view view) {             if (onitemclicklistener != null) {                 int position = getadapterposition();                 if (position != recyclerview.no_position) {                     onitemclicklistener.onitemclick(view, position);                 }             }         }     }      public interface onitemclicklistener {         void onitemclick(view itemview, int position);     }      private onitemclicklistener onitemclicklistener;     private list<t> items;      private final int layoutres;      public bindingrecyclerviewadapter(@layoutres int layoutres) {         this(layoutres, null, null);     }      public bindingrecyclerviewadapter(@layoutres int layoutres, collection<t> items) {         this(layoutres, items, null);     }      public bindingrecyclerviewadapter(@layoutres int layoutres, collection<t> items, onitemclicklistener onitemclicklistener) {         this.layoutres = layoutres;         this.items = (items == null) ? new arraylist<>() : new arraylist<>(items);         this.onitemclicklistener = onitemclicklistener;     }      @override     public viewholder oncreateviewholder(viewgroup parent, int viewtype) {         b binding = databindingutil.inflate(layoutinflater.from(parent.getcontext()), layoutres, parent, false);         return new viewholder(binding);     }      @override     public void onbindviewholder(viewholder holder, int position) {         t item = items.get(position);         bind(holder.binding, item, position);     }      @override     public void onviewrecycled(viewholder holder) {         recycle(holder.binding);     }      @override     public int getitemcount() {         return items.size();     }      protected abstract void bind(b binding, t item, int position);     protected abstract void recycle(b binding);      public onitemclicklistener getonitemclicklistener() {         return onitemclicklistener;     }      public void setonitemclicklistener(onitemclicklistener onitemclicklistener) {         this.onitemclicklistener = onitemclicklistener;     }      public list<t> getitems() {         return items;     }      public void setitems(collection<t> items) {         this.items.clear();          if (items != null) {             this.items.addall(items);         }          notifydatasetchanged();     }  } 

this caused reference problem, when setting comments this: this.comments = items; reference list of comments added adapter switched different list of items (but adapter still has reference old, empty list).

so solve this, instead of replacing comments new list of items, try adding items comments for-loop. loop through items , add them comments this:

for(timelinecommentmodel model: items) {     this.comments.add(model); } 

Comments

Popular posts from this blog

PySide and Qt Properties: Connecting signals from Python to QML -

c# - DevExpress.Wpf.Grid.InfiniteGridSizeException was unhandled -

scala - 'wrong top statement declaration' when using slick in IntelliJ -