EN

Android 小技巧 -3

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

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

技术复核(2026-10-13):原文发表于 2014 年,本译文发表于 2015 年。平台 android.app.Fragment 在 API 28 弃用,下面的 Fragment 建议改用 AndroidX;LocalBroadcastManager 与 Otto 已停止维护。其余条目保留原顺序,并补充 API 版本和使用边界。

正文

UrlQuerySanitizer——用来解析 URL 的 query 参数,并按配置的 ValueSanitizer 处理参数值。它不是完整 URL 的合法性或安全性检查器;scheme、host 和业务字段仍要按用途校验。还要明确未注册参数和重复参数的处理规则,避免把“成功解析”误当成“内容可信”。

Fragment.setArguments()——把可保存的初始化参数放进 Bundle。通常在创建 Fragment 实例之后、加入 FragmentManager 之前设置,这些参数可随 Fragment 的销毁和重建恢复。默认恢复机制使用无参构造;AndroidX Fragment 1.1.0 起可以通过 FragmentFactory控制实例化,所以“构造函数绝对不能有参数”也过于笼统。自定义工厂必须参与恢复过程。

DialogFragment.setShowsDialog()——同一个 DialogFragment 可以作为对话框,也可以嵌入页面。设置为 false 后不再以 Dialog 显示;需要在创建界面之前配置,并确保嵌入模式下 onCreateView() 能提供内容。只在 onCreateDialog() 里创建 Dialog 的布局,不会自动变成嵌入式 Fragment 的 View。

FragmentManager.enableDebugLogging()——旧的日志开关。AndroidX Fragment 1.2.0 已弃用这个方法,调试时可按官方说明执行 adb shell setprop log.tag.FragmentManager VERBOSE,再在 Logcat 中查看操作记录。

LocalBroadcastManager——进程内分发 Intent 的旧方案,在 1.1.0(2022 年) 已完全弃用且不再发布新版。新代码应按数据所有者和观察者的生命周期选择 LiveData 或响应式数据流。原文推荐的 Otto 1.3.8 也已弃用、仓库已归档,不再作为新的替代推荐;进程内事件总线更不能替代跨进程通信。

PhoneNumberUtils.formatNumber()——格式化的是电话号码,不是一般数字。旧的单 String 重载在 API 21 弃用;同版本新增的 formatNumber(phoneNumber, defaultCountryIso) 可以指定默认国家/地区代码,例如 CN。返回值可能为 null,调用方要保留合适的回退显示;格式化结果也不能证明号码真实存在。

Region.op()——对区域做交、并、差等运算。若要判断两个区域是否重叠,可以对结果 Region 执行 INTERSECT,再检查结果是否为空。Path 要先结合 clip 转成 Region;setPath() 得到的是无抗锯齿的像素区域,不能用它表示浮点路径边界的精确相交。op() 会修改接收结果的 Region,不只是一次只读比较。

Application.registerActivityLifecycleCallbacks()——从 API 14 起可注册本进程内 Activity 的生命周期回调,适合做统一观察;它不是监听手机上所有应用的接口。短期注册要在不再需要时注销,回调中也不要长期持有已经销毁的 Activity。

versionNameSuffix——Android Gradle Plugin 可以按 build type / product flavor 给版本名追加后缀,比如让 debug 版本显示 -SNAPSHOT。它只影响 versionName,不会改变安装标识或 versionCode。若要让 debug 与 release 并存,需要配置不同的 application ID,例如使用 applicationIdSuffix。

CursorJoiner——一个数据库里的数据,用 SQL JOIN 就能比较;如果数据来自两个独立的 ContentProvider 呢?CursorJoiner 可以比较两个 Cursor 的数据。前提是两边都按指定键列升序排列,并且每边的键元组唯一。它返回 LEFT、RIGHT、BOTH 来表示键的对应关系,不会生成一个新的 SQL 结果表,也不等价于任意多对多 JOIN。

Genymotion——Dan Lew 当时说自己整天都在用,评价是“快很多”。这款模拟器仍有桌面与云端产品,不过当年的感受不能当作它与当前 Android Emulator 的固定性能结论;比较时需要相同宿主、虚拟化条件、镜像架构和实际工作负载。

-nodpi——例如 res/drawable-nodpi/ 中的位图不按设备密度做自动资源缩放。它不控制 assets/ 文件,也不会让 dp、sp 或整个布局保持固定像素大小;ImageView 的尺寸和 scaleType 仍可能缩放最终显示。不要把它当成跨设备视觉尺寸一致的通用开关。

BroadcastReceiver.setDebugUnregister()——注册 receiver 前设为 true,系统会保留后续注销调用的堆栈,用来定位再次错误注销的问题。这个调试机制会把相关信息保留到进程结束,自身会造成泄漏,不能当作线上防泄漏方案。

Activity.recreate()——从 API 11 起可请求用新实例重建 Activity,适合检查页面恢复逻辑。它不是重启进程,也不会自动保存全部业务状态;需要按生命周期合同保存和恢复。

PackageManager.checkSignatures()——比较两个包的签名匹配关系,成功应检查 SIGNATURE_MATCH,不能把它仅当作“两个应用是否安装”的查询。包名相同并不意味着签名可信;Android 安装/更新本身也会检查签名,不能理解成两个不同签名的同包名应用可随意并装或覆盖。应用间授权还需要一个可信身份作为比较基准,并处理未知包和签名不匹配的结果。

备忘

More

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

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

关于我 && 博客

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

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

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

微信扫一扫

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