ITPub博客

首页 > 移动开发 > ANDROID > 解决setText()触发requestLayout导致View位置频繁刷新的问题

解决setText()触发requestLayout导致View位置频繁刷新的问题

原创 ANDROID 作者:山有木xi 时间:2024-05-14 20:46:40 0 删除 编辑

在我们的一个应用中有一个功能是需要显示时间的秒数分钟数等 , 正常的逻辑中 , 就是每秒去更新一次 Text View 的 set Text() 从而实现数据的显示 。 而当我们需要这个 TextVIew 能够移动时 , 却发现移动后每秒 TextVIew 都会重制位置

通过堆栈日志分析 , TextVIew 的 requestLayout 每秒都会被调用 , 再深入看 , 发现就是 set Text () 方法调用的

让我们看一下源码:

这其中的重点是第一:设置mPrivateFlags标记为需要重新layout,当下次View刷新周期到时,会触发其onMeasure和onLayout等方法进行布局计算;第二:调用其parent的requestLayout方法,即触发其父View也进行布局重计算。

到这里就知道为什么位置会被刷新了,如果调用子view的requestLayout进行布局重计算,其也会调用父View的requestLayout,一层一层传上去,直到rootView。

再回到我们遇到的问题,我们并没有直接调用requestLayout,而是调用了setText,setBackgroundDrawable这些方法,看来这些方法里面可能也调用了requestLayout从而导致其parent也进行了布局重计算。

于是我看了下setText方法,在里面发现了一行在之前排查堆栈信息时看到的关键的代码:checkForRelayout方法

点进去可以看到:

当View的LayoutParams是WRAP_CONTENT时,TextView会走到if中,在这里面涉及到了View的计算宽高,最后会调用到invalidate()和requestLayout()方法,也就是造成我们遇到的问题的罪魁祸首

看到这里时在想解决方法,想了几个思路

1、在 requestLayout调用后恢复View的位移信息

2、避免调用到 requestLayout

第一个方法,明显有种堆屎山的嫌疑,在TextView异常加载的基础上又额外的去加载位移操作,所以我把目光放在第二个点上,如何避免调用 requestLayout,按照源码中的逻辑,就是避免Text View的LayoutParams是WRAP_CONTEN

这样子又有两种思路

1、自定义TextView,手动判断以及设置TextView的宽高

2、修改布局,将宽度写死或者设置mach

在查看布局后选择第二种方案,因为我用的是约束布局,当我的TextView只设置了 layout_constraintStart_toStartOf或者 layout_constraintEnd_toEndOf,这时 WRAP_CONTEN和MACH _CONTEN其实效果一样

而在同时设置了 layout_constraintStart_toStartOf和 layout_constraintEnd_toEndOf的方案中,可以外面嵌套一层线下布局,让TextView在线性布局中设为 MACH _CONTEN即可解决问题

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69917874/viewspace-3015401/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
Oracle OCA(Java),IBM高级工程师认证,中国软件行业人才(高级c语言),高级Android工程师,对数据库并发与性能调优也有一定了解

注册时间:2019-04-25

  • 博文量
    147
  • 访问量
    390769