android app run onPreDraw infinitely -


step 1. create new app navigation drawer template.

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.

enter image description here

step 4. set breakpoint in onpredraw , see executed infinitely. if comment offsettopandbottom(50), goes fine.

enter image description here

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.

enter image description here

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

Popular posts from this blog

php - Vagrant up error - Uncaught Reflection Exception: Class DOMDocument does not exist -

vue.js - Create hooks for automated testing -

Add new key value to json node in java -