EN

Android 小技巧 - 4

字数统计: 1.6k阅读时长: 6 min
2015/03/15
loading

本文是一篇译文,这篇是这个系列的第四篇.讲述的是Android开发中遇到的一些好用的小技巧,或者一些实用的API,很多人都知道,但也有人不知道,记录下来,如果能帮助到大家,也是极好的.由于不是严格的博文,所以翻译也不那么严格,有些工具和类我也会经常用,所以我会根据自己的想法去写.有些地方作者并没有将这个工具的作用讲出来,我会补充上去.

技术复核(2026-10-13):这些 View/XML API 大多仍可用,但原文关于配置变化、裁剪和文件原子性的说明需要修正。Gradle 3.0 起默认启用 Daemon;AtomicFile 的实现则以下面的 Android 4.4.4 与 Android 16 源码对照说明。

正文

Activity.isChangingConfigurations()——从 API 11 起可以判断 Activity 是否正因配置变化而被销毁,用来区分销毁原因。它不会保存任何状态,不能据此跳过 onSaveInstanceState()、ViewModel 或持久化等合适的状态管理。也不要把任意时刻的 false 当作未来不会重建的保证;已经停止的 Activity 后续仍可能因配置变化被重建。

SearchRecentSuggestionsProvider——用于系统搜索框架中的最近查询建议。需要继承它,在构造函数中调用 setupSuggestions(),让 authority 与 manifest、searchable XML 中的配置一致。应用还要通过 SearchRecentSuggestions.saveRecentQuery() 保存查询,它不会自动记录所有输入或凭空生成一个搜索界面。

ViewTreeObserver——Dan Lew 当时常拿它来等 View 测量完成,再做动画。从 View 获取 observer 后,可以监听全局布局、预绘制等事件,等布局完成后读取尺寸。它不是主动测量 View 的接口;相关回调可能多次发生,只需要一次时应移除监听。长期保存 observer 引用时要检查 isAlive(),已失效的 observer 不能继续操作。

org.gradle.daemon=true——旧文通过复用 JVM 减少命令行构建的启动开销,这个思路仍然成立。不过 Gradle 3.0 起 Daemon 默认开启,现代项目通常不需要再加这一行才能启用。Daemon、增量构建和 build cache 是不同机制,不能把重复写一个配置项当成新的性能优化。

DatabaseUtils——集合了 Cursor 调试、查询和 ContentValues 转换等辅助方法。例如 cursorRowToContentValues() 处理当前行,dumpCursor() 便于调试。它不负责替调用方管理 Cursor 的完整生命周期;使用完仍需按数据所有权关闭资源。

android:weightSum(LinearLayout)——用于 LinearLayout 分配剩余空间时指定权重总和;没有显式设置时,会计算子 View 的 layout_weight 之和。显式总和大于子 View 权重之和时,可以保留部分未分配空间。实际大小还受子 View 的基础尺寸和父布局测量约束影响,不应把 weight 直接当成整个屏幕尺寸的百分比。

android:duplicateParentState(View)——让这个子 View 使用直接父 View 的 drawable state,例如 pressed、focused,而不是复制父 View 的所有属性和行为。它不会自动给子 View 添加点击监听。

android:clipChildren(ViewGroup)——默认 true,限制每个子 View 在自己的边界内绘制。设为 false 可以让子 View 的动画或自定义绘制越过自身边界,但更上层父容器仍可能裁剪。还需区分 clipToPadding;允许画出去也不会自动扩大布局尺寸和触摸命中区域。

android:fillViewport(ScrollView)——内容较短时,让直接子 View 的高度填满 ScrollView 的可用视口。它针对的是这个 ScrollView,不一定是整个屏幕;内容较长时仍正常滚动。ScrollView 只能有一个直接子 View,需要多个控件时用一个容器承载。

android:tileMode(BitmapDrawable)——定义位图平铺方式:repeat 重复图像,mirror 交替镜像,clamp 延伸边缘颜色;默认 disabled 不平铺。启用平铺后 gravity 会被忽略,它与 ImageView 的缩放策略不是同一个属性。

android:enterFadeDuration / android:exitFadeDuration——API 11 起可控制 DrawableContainer 切换子 Drawable 时的进入、退出渐变时长,单位是毫秒,例如状态列表切换时的淡入淡出。它控制渐变持续多久,不是先等一段时间再显示,也不是让整个 View 自动做入场动画。

android:scaleType(ImageView)——定义 Drawable 在 ImageView 内容区域中的缩放和裁剪。centerCrop 保持比例并覆盖内容区域,可能裁掉边缘;centerInside 保持比例,让图像完整放在内容区域内。这些策略影响显示,不会自动把原始大位图解码成合适的小图。

<merge>——作为布局文件根节点时,将子节点直接加入已有父容器,从而省掉一个不必要的 ViewGroup。复用布局文件用的是 <include>,<merge> 本身不是一个 View。用 LayoutInflater 加载它时需要有效的 parent 并立即 attach;如果原容器承担背景、padding 或交互职责,不能直接删掉。

AtomicFile——Dan Lew 提到,自己也写过类似功能,所以很高兴有了官方实现。框架类从 API 17 提供,用来更新单个文件。Android 4.4.4 使用 .bak 备份;Android 16 的实现先写 .new,再替换原文件,并兼容旧备份。startWrite() 后必须按成功或失败调用 finishWrite() / failWrite(),不能只关闭返回的流。它不提供线程或进程间文件锁,读写互斥仍由调用方保证,不能把“原子更新”理解成所有并发读写都安全。

备忘

More

  1. Part1
  2. Part2
  3. Part3
  4. Part4
  5. Part5

原文地址:https://blog.danlew.net/2014/05/12/android-tips-round-up-part-4/
原文作者:https://blog.danlew.net/about/
本文地址:https://www.androidperformance.com/2015/03/15/android-tips-round-up-4/ 转载请注明.

关于我 && 博客

下面是个人的介绍和相关的链接,期望与同行的各位多多交流,三人行,则必有我师!

  1. 博主个人介绍 :里面有个人的微信和微信群链接。
  2. 本博客内容导航 :个人博客内容的一个导航。
  3. 个人整理和搜集的优秀博客文章 - Android 性能优化必知必会 :欢迎大家自荐和推荐 (微信私聊即可)
  4. Android性能优化知识星球:付费社群已于 2026 年停止运营,不再招收新成员;此处保留历史介绍。

一个人可以走的更快 , 一群人可以走的更远

微信扫一扫

CATALOG
  1. 1. 正文
  2. 2. 备忘
    1. 2.1. More
  • 关于我 && 博客