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