问题现象

大概就是我们在自定义一个视频组件的ui时,发现了一段异常的效果。 我简述一下:

视频的控制器 底部一般都是 显示时间(textview)和进度条(seekbar)的

一般要实现这个效果 都是开个定时任务 每隔一段时间去重新setText一个时间。

效果如下:

然后测试mm们发现一个必现的异常,视频的进度条 也就是这个seekbar 总是会在视频开始的前几秒的时候

回退一下。然后才能正常展示进度条。

修复此问题的方法

经过一段时间的努力,我们发现 这个问题的解决方案 是把textview的 width属性 从wrap_content 改成 固定的xxdp值就可以。 问题的解决看似比较简单,但是背后的逻辑没有弄清楚。为什么把textview的属性

改了一下,这个关于seekbar的 问题就修复了?

还原问题现场

为了找到事情的根本原因,我们做了一次最小粒度还原。也就是新建一个干净的工程,排除其他问题的干扰,

看看到底是哪里出了问题?

首先看一下布局,这个布局和一开始我们出bug的布局是差不多的。

android:layout_width="match_parent"

android:layout_height="200dp"

android:background="@color/colorPrimary"

android:orientation="horizontal"

tools:ignore="MissingConstraints">

android:id="@+id/tv"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center_vertical"

android:gravity="center"

android:text="Hello World!" />

android:id="@+id/sb"

android:layout_width="100dp"

android:layout_height="match_parent"

android:layout_marginLeft="10dp">

复制代码

然后看一下我们的关键 复现问题的代码:

button = findViewById(R.id.bt);

button.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

new Thread() {

@Override

public void run() {

//每隔一段时间 去刷新一下界面

while (true) {

try {

Thread.sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

}

runOnUiThread(new Runnable() {

@Override

public void run() {

// 问题就在这里了,setText 以后 seekbar的状态会被莫名奇妙设置一次

tv.setText(System.currentTimeMillis() + "");

}

});

}

}

}.start();

}

});

复制代码

源码分析

首先我们看看为什么在wrap_content的时候 textview的setText 会导致一系列的问题?

跟一下 setText的源码:

我们把这个 函数整体贴上来

/**

* Check whether entirely new text requires a new view layout

* or merely a new text layout.

*/

@UnsupportedAppUsage

private void checkForRelayout() {

// If we have a fixed width, we can just swap in a new text layout

// if the text height stays the same or if the view height is fixed.

if ((mLayoutParams.width != LayoutParams.WRAP_CONTENT

|| (mMaxWidthMode == mMinWidthMode && mMaxWidth == mMinWidth))

&& (mHint == null || mHintLayout != null)

&& (mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight() > 0)) {

// Static width, so try making a new text layout.

int oldht = mLayout.getHeight();

int want = mLayout.getWidth();

int hintWant = mHintLayout == null ? 0 : mHintLayout.getWidth();

/*

* No need to bring the text into view, since the size is not

* changing (unless we do the requestLayout(), in which case it

* will happen at measure).

*/

makeNewLayout(want, hintWant, UNKNOWN_BORING, UNKNOWN_BORING,

mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight(),

false);

if (mEllipsize != TextUtils.TruncateAt.MARQUEE) {

// In a fixed-height view, so use our new text layout.

if (mLayoutParams.height != LayoutParams.WRAP_CONTENT

&& mLayoutParams.height != LayoutParams.MATCH_PARENT) {

autoSizeText();

invalidate();

return;

}

// Dynamic height, but height has stayed the same,

// so use our new text layout.

if (mLayout.getHeight() == oldht

&& (mHintLayout == null || mHintLayout.getHeight() == oldht)) {

autoSizeText();

invalidate();

return;

}

}

// We lose: the height has changed and we have a dynamic height.

// Request a new view layout using our new text layout.

requestLayout();

invalidate();

} else {

// Dynamic width, so we have no choice but to request a new

// view layout with a new text layout.

nullLayouts();

requestLayout();

invalidate();

}

}

复制代码

翻译一下,就是 只要满足一定的条件就不会触发 requestLayout这个操作。

稍微看看源码 也可以知道 这个条件,大概就是 宽度不要是wrap_content的属性,并且不能是跑马灯的属性。

当然对高度也有一定的要求,但是最重要的条件就是width的wrap_content属性(其他属性我们用的比较少),只要不是他,我们就不会

走到requestLayout的流程中。

原因真的分析完毕了吗?

再仔细想一想,在一个view树中,一个子view的重绘 必定会导致 整个view树 全部进行重绘吗?

看一下view本身的源码

我们翻译一下这段代码 其实就是

只要View自己没有requestLayout或者再次measure时,MeasureSpec没变,就不需要重新measure

所以得出来一个结论,虽然 在满足width 等于wrap content的情况下,setText会触发 requestLayout,

但是 这并不一定导致 这个textview的兄弟节点 每次都会measure。 这也就是这个bug的表象是

只有第一次setText会导致seekbar 重绘进而造成bug,但是后面的setText 都不会导致seekBar重绘的真正原因了。

结论

对于textview这样的控件而言,setText是有一个隐形的触发界面重绘的操作,我们在周期性的对textview的

setText方法进行调用时,一定多加考虑,最好将textview的宽度设置成固定值或者是match,避免引发各种奇葩bug,或者是降低了界面渲染的效率。 特别是对于我们动画功能的编写,一定要多去看看api,看看这个api下面是不是会引发requestLayout,从而提高效率。

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[Android性能优化-TextView的setText方法会导致界面重绘?]http://www.zyiz.net/tech/detail-115674.html

Android里面的settext作用,Android性能优化-TextView的setText方法会导致界面重绘?相关推荐

  1. android 单例的作用,Android中单例模式的几个坑

    先来看这样一个单例,稍微有点经验的同学可能都会说,这样的单例是非线程安全的.要加个volatile关键字才可以.class Singleton{        private static  Sing ...

  2. Java中性能优化的35种方法汇总

    原文地址:http://www.jb51.net/article/102831.htm 前言 对程序员们来说,代码优化是一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于 ...

  3. MySQL性能优化的9种方法

    MySQL性能优化的9种方法 1.选择最合适的字段属性 Mysql是一种关系型数据库,可以很好地支持大数据量的存储,但是一般来说,数据库中的表越小,在它上面执行的查询也就越快.因此,在创建表的时候,为 ...

  4. golang string 加号连接性能慢_面试必备:浅析C#性能优化的若干种方法

    浅析C#性能优化的若干种方法 1.1 垃圾回收 垃圾回收解放了手工管理对象的工作,提高了程序的健壮性,但副作用就是程序代码可能对于对象创建变得随意. 1.1.1 避免不必要的对象创建 由于垃圾回收的代 ...

  5. DB2设计与性能优化:原理、方法与实践

    DB2设计与性能优化:原理.方法与实践 王飞鹏  陈辉  张广舟  成孜论  编著 ISBN 978-7-121-13094-6 2011年4月出版 定价:89.80元(含光盘1张) 16开 416 ...

  6. Vmware虚拟机里面的linux系统ping不通宿主机的解决方法(注意同时安装vmware和vbox虚拟机)

    Vmware虚拟机里面的linux系统ping不通宿主机的解决方法(注意同时安装vmware和vbox虚拟机) 参考文章: (1)Vmware虚拟机里面的linux系统ping不通宿主机的解决方法(注 ...

  7. php性能优化的几个方法

    核心提示:本文主要讲述php性能优化的几个方法相关内容:PHP是一种在服务器端执行的脚本语言,它开发了世界上许多知名的网站,包括雅虎和Facebook等.下面介绍的几条PHP代码.性能优化的技巧供读者 ...

  8. android strictmode有什么作用,Android 性能优化 之 StrictMode

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? StrictMode概述 StrictMode 是用来检测程序中违例情况的开发者工具.使用StrictMode,系统检测 ...

  9. Android:最全面详细的性能优化攻略(含内存优化、内存泄漏、绘制优化、布局优化、图片优化、APK优化、多线程优化、列表优化等)

    前言:佛教中有一句话:初学者的心态,拥有初学者心态是件了不起的事情.真正的大师永远怀有一颗学徒的心. 一.概述 在Android中,性能优化是细分领域中最难且也是知识面涉及最深和最广的方向之一. 更快 ...

最新文章

  1. 十三、序列化和反序列化(部分转载)
  2. 年中盘点:2021年炙手可热的10家数据科学和机器学习初创公司
  3. 解决jquery的多次绑定事件
  4. 金算盘高手论坛资料中心_3D006期 菜鸟论坛精英PK专栏 速来围观!!
  5. 使用VS Code开发.Net Core 2.0 MVC Web应用程序教程之一
  6. LeetCode 670. 最大交换
  7. mysql刻度转时分秒
  8. 围成面积(信息学奥赛一本通-T1359)
  9. jenkins2 pipeline实例
  10. 【秒懂音视频开发】16_AAC解码实战
  11. 鸟哥的Linux私房菜-服务器架设篇
  12. 26丨案例:手把手带你理解TPS趋势分析*
  13. 美国国防科研情报追踪系统发布,200余所美国实力高校尽收眼底!
  14. 淘宝的直播视频怎么下载啊?有好的方法没有,越简单越好
  15. 安装R语言(Rstudio、R、RTools)
  16. word段落居中的快捷键_word里段落的快捷键 WORD中段落的快捷键是什么
  17. (入门级web应用)小书签收集站开发日志(一)--项目规划及最基本功能实现
  18. 路由器 刷 linux系统版本,一个小型的无线路由器 Linux 系统OpenWRT[转]
  19. 使用Kindle4rss推送自己感兴趣的博文
  20. 基于Python的K近邻算法实现

热门文章

  1. Cesium集成WebXR_连接VR设备
  2. 用js原生控制台输出一个金字塔
  3. java 多线程 安全 源码,纯干货,从源码解析多线程与高并发,再说不会,我再也不踏足IT圈...
  4. 计算机应用基础小课题,计算机应用基础3课题.doc
  5. 前端登录时,含有特殊字符被转义的解决方案
  6. iPad开发:UISplitViewController应用
  7. node爬虫(伪造header)
  8. c语言编程计算人口增长模式介绍,C语言所有题目以及结果解析.doc
  9. 微信公众号文章如何使用其他字体
  10. wordpress手把手仿站操作