李林LiLin
Android之View绘制问题汇总
原创
关注作者
前往小程序,Get
更优
阅读体验!
立即前往
腾讯云
开发者社区
文档
建议反馈
控制台
登录/注册
首页
学习
活动
专区
工具
TVP
最新优惠活动
文章/答案/技术大牛
搜索
搜索
关闭
发布
首页
学习
活动
专区
工具
TVP
最新优惠活动
返回腾讯云官网
李林LiLin
首页
学习
活动
专区
工具
TVP
最新优惠活动
返回腾讯云官网
社区首页
>
专栏
>
Android之View绘制问题汇总
Android之View绘制问题汇总
原创
李林LiLin
关注
修改于 2023-03-06 20:01:33
1.1K
0
修改于 2023-03-06 20:01:33
举报
文章被收录于专栏:
Android进阶编程
1、MeasureSpec是什么?
MeasureSpec是一种“测量规则”或者“测量说明书”,决定了View的测量过程
View的MeasureSpec会根据自身的LayoutParamse和父容器的MeasureSpec生成。
最终根据View的MeasureSpec测量出View的宽/高(测量时数据并非最终宽高)
2、MeasureSpec的组成?
MeasureSpec代表一个32位int值,
高2位是SpecMode,低30位是SpecSize
SpecMode是指测量模式
SpecSize是指在某种测量模式下的大小
类MesaureSpec提供了用于SpecMode和SpecSize打包和解包的方法
3、测量模式SpecMode的类型和具体含义?
UNSPECIFIED:父容器不对View有任何限制,一般用于系统内部
EXACTLY:精准模式,View的最终大小就是SpecSize指定的值(对应于LayoutParams的match_parent和具体的数值)
AT_MOST:最大值模式,大小不能大于父容器指定的值SpecSize(对应于wrap_content)
4、MeasureSpec和LayoutParams的对应关系?
View的MeasureSpec是需要通过自身的LayoutParams和父容器的MeasureSpec一起才能决定
DecorView(顶级View)是例外,其本身MeasureSpec由窗口尺寸和自身LayoutParams共同决定
MeasureSpec一旦确定,onMeasure中就可以确定View的测量宽/高
5、如何获取View的测量宽/高?
在measure完成后,可以通过getMeasuredWidth/Height()方法,就能获得View的测量宽高
在一定极端情况下,系统需要多次measure,因此得到的值可能不准确,最好的办法是在onLayout方法中获得测量宽/高或者最终宽/高
6、如何在Activity启动时获得View的宽/高?
Activity的生命周期与View的measure不是同步运行,因此在onCreate/onStart/onResume均无法正确得到
若在View没有测量好时,去获得宽高,会导致最终结果为0
7、Activity中获得View宽高的4种办法?
onWindowFocusChanged
View已经初始化完毕,可以获得宽高,Activity得到焦点和失去焦点均会调用一次(频繁onResume和onPause会导致频繁调用)
view.post(runnable)
通过post将一个runnable投递到消息队列尾部,等到Looper调用次runnable时,View已经完成初始化
ViewTreeObserver
使用ViewTreeObserver的接口,可以在View树状态改变或者View树内部View的可见性改变时,onGlobalLayout会被回调,能正确获取View宽/高
view.measure
8、Activity启动到最终加载ViewRoot(执行三大流程)的流程是什么?
Activity调用startActivity方法,最终会调用ActivityThread的handleLaunchActivity方法
handleLaunchActivity会调用performLauchActivity方法(会调用Activity的onCreate,并完成DecorView的创建)和handleResumeActivity方法
handleResumeActivity方法会做四件事:
performResumeActivity(调用activity的onResume方法)
getDecorView(获取DecorView)
getWindowManager(获取WindowManager)
WindowManager.addView(decor, 1)
WindowManager.addView(decor, 1)本质是调用WindowManagerGlobal的addView方法。其中主要做两件事:
创建ViewRootImpl实例
root.setView(decor, ….)将DecorView作为参数添加到ViewRoot中,这样就将DecorView加载到了Window中
ViewRootImpl还有一个方法performTraveals方法,用于让ViewTree开始View的工作流程:其中会调用performMeasure/Layout/Draw()三个方法,分别对应于View的三大流程。
9、自定义View性能优化有哪些?
避免过度绘制
像素点能画一次就不要多次绘制,以及绘制看不到的背景。开发者选项里内的工具,只对xml布局有效果,看不到自定义View的过度绘制,仍然需要注意。
尽量减少或简化计算
不要做无用计算。尽可能的复用计算结果。
应该避免在for或while循环中做计算。比如:去计算屏幕宽度等信息。
避免创建大量对象造成频繁GC
应该避免在for或while循环中new对象。这是减少内存占用量的有效方法。
禁止或避免I/O操作
I/O操作对性能损耗极大,不要在自定义View中做IO操作。
onDraw中避免冗余代码、避免创建对象
onDraw中禁止new对象。如:不应该在ondraw中创建Paint对象。Paint类提供了reset方法。可以在初始化View时创建对象。
要避免冗余代码,提高效率。
复合View,要减少布局层级。
复合控件:继承自现有的LinearLayout等ViewGroup,然后组合多个控件来实现效果。这种实现方法要注意减少布局层级,层级越高性能越差。
状态和恢复和保存
Activity还会因为内存不足或者旋转屏幕而导致重建Activity,自定义View也要去进行自我状态的保存和读取。
在onSaveInstanceState()保存状态;在onRestoreInstanceState()恢复状态
开启硬件加速
合理使用invalidate的参数版本。
避免任何情况下调用默认参数的invalidate
调用有参数的invalidate进行局部和子View刷新,能够提高性能。
减少冗余代码
不要使用Handler,因为已经有post系列方法,View已经有post系列方法,没有必要重复去写,可以直接使用,最终会投递到主线程的Handler中
使用的线程和动画,要在onDetachedFromWindow中进行清理工作。
View如果有线程或者动画,需要及时停止,View的onDetachedFromWindow会在View被remove时调用,在该方法内进行终止。这样能避免内存泄露
要妥善处理滑动冲突。
View如果有滑动嵌套情形,需要处理好滑动冲突
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系
cloudcommunity@tencent.com
删除。
http
容器
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系
cloudcommunity@tencent.com
删除。
http
容器
#View的绘制
评论
登录
后参与评论
0 条评论
热度
最新
推荐阅读
LV.
文章
0
获赞
0
目录
1、MeasureSpec是什么?
2、MeasureSpec的组成?
3、测量模式SpecMode的类型和具体含义?
4、MeasureSpec和LayoutParams的对应关系?
5、如何获取View的测量宽/高?
6、如何在Activity启动时获得View的宽/高?
7、Activity中获得View宽高的4种办法?
8、Activity启动到最终加载ViewRoot(执行三大流程)的流程是什么?
9、自定义View性能优化有哪些?
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
产品介绍
产品文档
11.11 上云拼团GO
领券
问题归档
专栏文章
快讯文章归档
关键词归档
开发者手册归档
开发者手册 Section 归档
0
0
0
推荐