android - Why notifyItemChanged only works in post Runnable after setAdapter? -
public class mainactivity extends appcompatactivity { @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); recyclerview list = (recyclerview) findviewbyid(r.id.list); list.setlayoutmanager(new linearlayoutmanager(this)); final recyclerview.adapter adapter = getadapter(); list.setadapter(adapter); adapter.notifyitemchanged(1, new object());//this doesn't work list.post(new runnable() { @override public void run() { adapter.notifyitemchanged(1, new object());//this works } }); } @nonnull private recyclerview.adapter getadapter() { return new recyclerview.adapter() { @override public recyclerview.viewholder oncreateviewholder(viewgroup parent, int viewtype) { return new itemviewholder( layoutinflater.from(parent.getcontext()) .inflate(r.layout.list_view_item, parent, false)); } @override public void onbindviewholder(recyclerview.viewholder holder, int position) { itemviewholder item = (itemviewholder) holder; item.tv.settext("test"); } @override public void onbindviewholder(recyclerview.viewholder holder, int position, list payloads) { if(payloads.isempty()) onbindviewholder(holder, position); else{ itemviewholder item = (itemviewholder) holder; item.tv.settext("changed!!!!!! "); } } @override public int getitemcount() { return 40; } class itemviewholder extends recyclerview.viewholder{ textview tv; itemviewholder(view itemview) { super(itemview); tv = (textview) itemview.findviewbyid(r.id.tv); } } }; }} very simple example here test notifyitemchanged, works when post message queue, not invoking directly after setadapter. setadapter triggers call requestlayout(), mean notifyitemchanged can't happen if in middle of laying out items?
after bit of investigation turns out notifyitemchanged works when recyclerview attached , has completed onlayout happens after oncreate.
internally during recyclerview.onlayout() called notifyitemchanged -> requestlayout(), processadapterupdatesandsetanimationflags() called checks if item updated has available viewholder in case null because during oncreate(), recyclerview not attached window, no measurement , layout has done recyclerview
apparently complete drawing of recyclerview happens sometime after oncreate() , onresume()
@override protected void onresume() { super.onresume(); boolean = list.isattachedtowindow();//this false! } so make notifyitemchanged work on oncreate
list.addonlayoutchangelistener(new view.onlayoutchangelistener() { @override public void onlayoutchange(view v, int left, int top, int right, int bottom, int oldleft, int oldtop, int oldright, int oldbottom) { adapter.notifyitemchanged(1, new object());//this update item } }); new thread((new runnable() { @override public void run() { try { thread.sleep(28);//small amount of delay,below 20 doesn't seem work } catch (interruptedexception e) { e.printstacktrace(); } runonuithread(new runnable() { @override public void run() { adapter.notifyitemchanged(1, new object());//also works } }); } })).start(); i guess reason viewrootimpl.performtraversal() controlled system , happens sometime after decorview attached window during oncreate
i'm assuming can happen during oncreate , onresume, may not happen if called later.
Comments
Post a Comment