Example explanation of android listening to View loading completion

  • 2021-10-16 02:33:19
  • OfStack

In the recent project, it is necessary to implement an GridView to display 6*5=30 items, and cover the whole interface. There are other controls such as custom ActionBar in the interface, so it is necessary to obtain the height of the remaining screen. It is known from Baidu that View has a monitoring function, which is effective for pro-testing. This is hereby recorded for future reference.


gv_test.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
   @Override
   public void onGlobalLayout() {
    // To GridView Settings Adapter , in adapter Adj. getView Get from GridView The height obtained before this callback is the height of 0
    // After processing remove Drop, as for why, there is an explanation later 
    gv_test.getViewTreeObserver()
    .removeOnGlobalLayoutListener(this);
   }
  });

Tracing back through the source code, find ViewTreeObserver this class, there are many interface, are used to track View various state changes.

Find OnGlobalLayoutListener


/**
  * Interface definition for a callback to be invoked when the global layout state
  * or the visibility of views within the view tree changes.
  */
 public interface OnGlobalLayoutListener {
  /**
   * Callback method to be invoked when the global layout state or the visibility of views
   * within the view tree changes
   */
  public void onGlobalLayout();
 }

The general meaning of the annotation is that this callback is called back when the layout state and visible state change, so to be precise, this is not to listen for the loading completion of View, but to listen for the layout change.

Let's test 1.


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context="com.example.myapplication.MainActivity">

 <Button
  android:onClick="test"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:text="test"/>

 <TextView
  android:id="@+id/tv_test"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text=" Test "/>
</LinearLayout>

public class MainActivity extends AppCompatActivity {

 TextView tv_test;
 private static final String TAG = "MainActivity";
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  setContentView(R.layout.activity_main);

  tv_test = (TextView)findViewById(R.id.tv_test);
  //app Switch to the background, and then click the meeting call 1 When the screen is closed, the running program will be called twice 
  tv_test.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
   @Override
   public void onGlobalLayout() {
    Log.e(TAG, "onGlobalLayout: ");
   }
  });
 }



 public void test(View v){
  // Change visibility, call 1 Times 
//  tv_test.setVisibility(View.GONE);
  // Change the text layout, no effect 
//  tv_test.setGravity(Gravity.CENTER);

  // Modify the control size, call the 1 Times 
//  LinearLayout.LayoutParams para = (LinearLayout.LayoutParams) tv_test.getLayoutParams();
//  para.height = 200;
//  para.weight = 100;
//  tv_test.setLayoutParams(para);

  // Modify layoutgravity , this is in LayoutParams Call the 1 Times 
  LinearLayout.LayoutParams para = (LinearLayout.LayoutParams) tv_test.getLayoutParams();
  para.gravity = Gravity.CENTER_HORIZONTAL;
  tv_test.setLayoutParams(para);
 }
}

Running the program, we can see from android monitor that we called onGlobalLayout three times after startup, which is very strange. Why is it three times? Later, the screen was locked once, and it was found that it was called twice. After testing, app will be called once when it reenters after retreating to the background, and twice when it is reopened after the screen is locked (millet twice, Nubia once), among which one guess is that the visibility of the control has changed.

Through the key test, the visibility and layout of the control are modified once, while the internal layout of the control is modified, but not called. At the same time, the layout and visibility are modified, only called once.

The mystery of this three times remains unsolved, but it is certain that this will be repeated

Called many times, you should pay attention when using it. The solution is to drop the callback remove after the first callback, such as gv_test. getViewTreeObserver ()

.removeOnGlobalLayoutListener(this);

If there are any mistakes, please be honest.


Related articles: