返回

揭秘View#requestLayout()的幕后运作:受影响View大起底!

Android

调用View#requestLayout(),牵一发而动全身

当您调用View#requestLayout()方法时,它会引发一连串的事件,影响到多个View。这些受影响的View包括:

  1. 发起requestLayout()调用的View:

    • 该View会标记自身为需要重新布局,即设置其mPrivateFlags中的PFLAG_FORCE_LAYOUT标志位。
    • 同时,它也会将PFLAG_FORCE_LAYOUT标志位传播给它的所有父View ,直至ViewRootImpl
  2. 各级父View(直到ViewRootImpl):

    • 这些父View也会标记自身为需要重新布局,即设置它们的mPrivateFlags中的PFLAG_FORCE_LAYOUT标志位。
  3. 发起requestLayout()调用的View及其所有父View:

    • 这些View会依次调用它们的invalidate()方法,触发重绘。
    • 重绘过程会从发起requestLayout()调用的View开始,依次向上遍历它的父View,直到ViewRootImpl
  4. 发起requestLayout()调用的View及其所有父View:

    • 这些View会依次调用它们的measure()方法,触发重新测量。
    • 重新测量过程也会从发起requestLayout()调用的View开始,依次向上遍历它的父View,直到ViewRootImpl
  5. 发起requestLayout()调用的View及其所有父View:

    • 这些View会依次调用它们的layout()方法,触发重新布局。
    • 重新布局过程也会从发起requestLayout()调用的View开始,依次向上遍历它的父View,直到ViewRootImpl

影响范围的背后逻辑

上述影响范围的背后逻辑在于,View#requestLayout()方法会触发View的重新布局,而重新布局过程需要从发起requestLayout()调用的View开始,依次向上遍历它的父View,直到ViewRootImpl。在这个过程中,所有经过的View都会受到影响,包括:

  • 需要重新布局的View: 这些View会标记自身为需要重新布局,并依次向上传播PFLAG_FORCE_LAYOUT标志位。
  • 需要重绘的View: 这些View会调用它们的invalidate()方法,触发重绘。
  • 需要重新测量的View: 这些View会调用它们的measure()方法,触发重新测量。
  • 需要重新布局的View: 这些View会调用它们的layout()方法,触发重新布局。

优化建议

了解了View#requestLayout()方法的影响范围后,我们就可以针对性地进行优化,以提高布局性能。一些优化建议包括:

  • 避免在不需要的时候调用requestLayout()方法。
  • 尽量减少发起requestLayout()调用的View的数量。
  • 使用invalidate()方法代替requestLayout()方法,以避免不必要的重新布局。
  • 使用measure()方法代替requestLayout()方法,以避免不必要