为什么在invalidate之后直接调用requestLayout

时间:2016-02-08 21:09:25

标签: android android-view android-view-invalidate

我正在了解自定义视图,想了解@RestController public class ProductController { private ProductRequestValidator productRequestValidator; @InitBinder public void initBinder(WebDataBinder binder){ binder.addValidators(productRequestValidator); } @Autowired public ProductController(ProductRequestValidator productRequestValidator, ProductService productService) { this.productRequestValidator = productRequestValidator; } @RequestMapping(value = "/products", method = RequestMethod.GET) public List<ProductResponse> retrieveProducts(@Valid @RequestBody ProductRequest requestProduct, BindingResult bindingResult) throws ValidationException { // validate input and throw exception if any error occured if (bindingResult.hasErrors()){ throw new ValidationException(bindingResult); } // business logic return new ProductRequest(); } invalidate()

请参阅此答案及其图表:

  

https://stackoverflow.com/a/25846243/4243687

requestLayout()告诉Android视图状态已更改,需要重新绘制。

invalidate()表示视图的大小可能已更改,需要重新测量,然后重新绘制。

requestLayout()将调用invalidate()dispatchDraw()draw(),因此会重新呈现视图。

另一方面,

onDraw()几乎可以完成从测量到重新渲染的所有内容。

为什么那么多示例(甚至是requestLayout()源代码)在下一行调用TextView然后invalidate()

4 个答案:

答案 0 :(得分:11)

invalidate()专门用于重绘视图内容。重绘不会同步发生。相反,它会将视图区域标记为无效,以便在下一个渲染周期中重绘它。

当其中的某些内容可能改变其尺寸时,应使用

requestLayout()。在这种情况下,父视图和视图层次结构中的所有其他父级都需要通过布局传递重新调整自己。

如果您没有对您的观点做任何会改变其大小的内容,那么您就不必致电requestLayout()

如果您回过头来查看TextView代码中调用requestLayout()的地方的位置,那么它将会影响视图的界限。例如,setPadding()setTypeface()setCompoundDrawables()

因此,当调用requestLayout()时,应该调用invalidate以确保重绘整个视图。

答案 1 :(得分:9)

看到the following diagram后,我认为调用requestLayout()最终会产生onDraw

enter image description here

因此,没有必要将这些调用在一起,因为它是多余的。

invalidate();
requestLayout();

然而,事实证明该图表具有误导性。有些视图实际上可能会在布局更改时自行失效,但这不是确定的。 无法保证致电requestLayout()会导致onDraw被调用。

我的source(感谢this comment)是Romain Guy(谷歌的Android工程师):

  

requestLayout()本身并不会导致绘制传递,而是一些视图   可能会通过调用invalidate来对布局更改做出反应。

因此,要确定重新布局会导致重绘,那么您应该将invalidate()requestLayout()配对。 (但事实并非如此。如果您只需要重绘,则无需拨打requestLayout()。单个invalidate()即可。)

答案 2 :(得分:2)

回答问题的书Expert Android的相关摘录:

  

因为onClick事件导致维度发生变化,我们的   视图需要变大,占用更多空间。我们如何表达   那需要Android,嗯,我们请求Layout()。这种方法上升了   链,标记每个视图父母需要重新测量。   当最终父级获得此请求(视图根)时,父级   安排布局遍历。布局遍历可能会也可能不会产生   在onDraw中,虽然在这种情况下它应该。作为一个很好的编程   练习时,我们也调用invalidate()来确保绘图阶段为   好。

答案 3 :(得分:0)

Android docs: Creating a View class

D:\GitHub\facebook-sdk-for-unity [tmp-test-bashscripts]> sh .\scripts\setup.sh
/d/GitHub/facebook-sdk-for-unity/scripts/local.properties: line 1: sdk.dir=D:\Android\android-sdk\sdk: No such file or directory
sed: can't read /FacebookSdkVersion.cs: No such file or directory
.\scripts\setup.sh: line 25: buildAndCopyCore: command not found
.\scripts\setup.sh: line 26: buildAndCopyPlatformDLLs: command not found
/d/GitHub/facebook-sdk-for-unity/scripts/local.properties: line 1: sdk.dir=D:\Android\android-sdk\sdk: No such file or directory
sed: can't read /FacebookSdkVersion.cs: No such file or directory
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 75.1M  100 75.1M    0     0   359k      0  0:03:33  0:03:33 --:--:--  372k
**/d/GitHub/facebook-sdk-for-unity/scripts/local.properties: line 1: sdk.dir=D:\Android\android-sdk\sdk: No such file or directory**
sed: can't read /FacebookSdkVersion.cs: No such file or directory
\033[0;36mStarting build \033[0m
\033[0;36mStep 1 - Cleaning wrapper libs folder \033[0m
/d/GitHub/facebook-sdk-for-unity/facebook-android-wrapper/libs /d/GitHub/facebook-sdk-for-unity
find: warning: you have specified the -maxdepth option after a non-option argument !, but options are not positional (-maxdepth affects tests specified before it as well as those specified after it).  Please specify options before other arguments.

/d/GitHub/facebook-sdk-for-unity
\033[0;36mStep 2 - Get depenancies for android wrapper \033[0m
\033[0;36mStep 2.1.0 - Download bolts-android-1.4.0.jar \033[0m
\033[0;36mbolts-android-1.4.0.jar already exists. Skipping download. \033[0m
\033[0;36mStep 2.1.1 - Download bolts-tasks-1.4.0.jar \033[0m
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   178  100   178    0     0    546      0 --:--:-- --:--:-- --:--:--   642
100   190  100   190    0     0    212      0 --:--:-- --:--:-- --:--:--   690
100 38092  100 38092    0     0  28892      0  0:00:01  0:00:01 --:--:-- 28892
\033[0;36mStep 2.1.2 - Download bolts-applinks-1.4.0.jar \033[0m
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   178  100   178    0     0    650      0 --:--:-- --:--:-- --:--:--   661
100   196  100   196    0     0    233      0 --:--:-- --:--:-- --:--:--   233
100 25020  100 25020    0     0  20337      0  0:00:01  0:00:01 --:--:--  228k
\033[0;36mStep 2.2 - Download facebook-android-sdk-4.14.0.aar \033[0m
\033[0;36mfacebook-android-sdk-4.14.0.aar already exists. Skipping download \033[0m
\033[0;36mStep 2.3 - Coping support lib \033[0m
\033[0;36mStep 3 - Build android wrapper \033[0m
/d/GitHub/facebook-sdk-for-unity/facebook-android-wrapper /d/GitHub/facebook-sdk-for-unity
**/d/GitHub/facebook-sdk-for-unity/scripts/setup_android_unity_plugin.sh: line 118: ./gradlew: No such file or directory**

\033[0;31mFATAL: Failed to perform gradle clean \033[0m

\033[0;31mFATAL: Failed to build the android sdk plugin \033[0m
  

请注意,setShowText调用invalidate()和requestLayout()。这些   调用对于确保视图可靠地运行至关重要。你有   在对可能的属性进行任何更改后使视图无效   改变它的外观,以便系统知道它需要   重绘。同样,如果属性,您需要请求新的布局   可能影响视图大小或形状的更改。忘记   这些方法调用可能导致难以发现的错误。