android app run onPreDraw infinitely -
step 1. create new app navigation drawer template.
step 2. add customized button , override onmeasure method.
@coordinatorlayout.defaultbehavior(mybutton.behavior.class) public class mybutton extends android.support.v7.widget.appcompatbutton { private viewtreeobserver.onpredrawlistener mpredrawlistener; public mybutton(context context) { super(context); } public mybutton(context context, attributeset attrs) { super(context, attrs); } public mybutton(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); } @override protected void onmeasure(int widthmeasurespec, int heightmeasurespec) { super.onmeasure(widthmeasurespec, heightmeasurespec); if (mpredrawlistener == null) { mpredrawlistener = new viewtreeobserver.onpredrawlistener() { @override public boolean onpredraw() { offsettopandbottom(50); return true; } }; viewparent p = getparent(); if (p instanceof view) { if (build.version.sdk_int >= build.version_codes.jelly_bean) { ((view)p).getviewtreeobserver().addonpredrawlistener(mpredrawlistener); } } } } public static class behavior extends coordinatorlayout.behavior<mybutton> { @override public boolean onlayoutchild(coordinatorlayout parent, mybutton child, int layoutdirection) { final list<view> dependencies = parent.getdependencies(child); return super.onlayoutchild(parent, child, layoutdirection); } @override public void onattachedtolayoutparams(@nonnull coordinatorlayout.layoutparams lp) { if (lp.dodgeinsetedges == gravity.no_gravity) { // if developer hasn't set dodgeinsetedges, lets set bottom // dodge snackbars lp.dodgeinsetedges = gravity.bottom; } } }
}
step 3. use mybutton
in app_bar_main layout.
step 4. set breakpoint in onpredraw , see executed infinitely. if comment offsettopandbottom(50)
, goes fine.
i trace source code , find app receive vsync signal again , again cause onvsync
function in choreographer.java run infinitely. why happens?
update
if set breakpoint below , comment onpredraw
, breakpoint not reached, otherwise, can reached always.
the callback onpredraw()
called before each frame drawn. since keep on drawing frames (~60fps), normal called "infinitely".
to avoid behavior, usual pattern remove listener first statement in onpredraw()
:
view.getviewtreeobserver().removeonpredrawlistener(this);
where view
downcasted parent in case.
you can see example code in this video. engineers part of android framework team.
Comments
Post a Comment