EN

Android 小技巧 - 5

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

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

技术复核(2026-10-13):原文发表于 2014 年,本译文发表于 2015 年。旧 Support Library 链接改为 AndroidX;外部存储、缩略图和应用语言补充新版本用法。清除应用数据和数据库让出事务的副作用也在对应条目中明确说明。

正文

ViewDragHelper——帮助自定义 ViewGroup 处理子 View 拖拽和滑动,现使用 androidx.customview.widget 中的版本。可以参考 AndroidX DrawerLayout;使用 helper 仍需由容器接入触摸事件并实现相应回调,不是实例化后所有 View 就自动可拖动。原文的 Flavien Laurent 文章保留为历史链接,本次未能重新访问。

PopupWindow——在当前 Activity 上方展示临时浮层,可用来承载菜单、提示或其他 View。它依附已有窗口,不能因为没有新建 Activity 就把它当作可任意覆盖其他应用的系统悬浮窗。焦点、触摸与输入法行为需要按实际交互配置。

ActionBar.getThemedContext()——API 14 起提供带 ActionBar 主题的 Context。为 ActionBar 创建自定义 View 时,使用它可以获得与导航栏一致的主题。先确认当前页面确实有 ActionBar;采用无 ActionBar 主题时,不能直接对 getActionBar() 的结果调用方法。

ThumbnailUtils——框架类从 API 8 提供。旧 createVideoThumbnail(String, int) 在 API 29 弃用,同版本新增 createVideoThumbnail(File, Size, CancellationSignal),可指定尺寸并取消操作。有直接文件访问权时使用 File 版本;面对内容提供方的 Uri,可使用同为 API 29 的 ContentResolver.loadThumbnail()。缩略图生成可能涉及解码与 I/O,应在后台处理,并处理失败或取消结果。

Context.getExternalFilesDir()——API 8 起返回本应用的外部存储专属目录,内容随应用卸载删除。从 Android 4.4 KitKat / API 19 起,访问自己的该目录不需要存储权限;原文的“Android 4.0 Kitkat”有误。外部存储不一定是可拔出的 SD 卡,不可用时返回值可能为 null。Android 10 引入分区存储;在 Android 11 上面向 API 30 及以上时,WRITE_EXTERNAL_STORAGE 不再增加写入范围,不能沿用“申请权限后任意写 SD 卡”的说法。Android 11 存储变化

SparseArray——针对 int 键节省内存,避免 Integer 装箱和每项额外的 HashMap entry 对象。它内部使用数组和二分查找,不是所有操作都比 HashMap 快,也不实现通用 Map 接口。是否适合还要看元素数量和增删模式;SparseBooleanArray、SparseIntArray、SparseLongArray 分别提供对应的基本类型值容器。

PackageManager.setComponentEnabledSetting()——改变 manifest 中组件的启用状态,不是启动该组件。显式启用/禁用会覆盖原状态,COMPONENT_ENABLED_STATE_DEFAULT 恢复 manifest 配置。DONT_KILL_APP 表示请求不杀所属应用,但修改组件状态仍会影响后续行为;不要把关闭 receiver 等同于已经停止所有相关业务工作。

SQLiteDatabase.yieldIfContendedSafely()——存在竞争并实际让出时,会把此前事务按成功结束,再开启一个新的、尚未标记成功的事务,让其他线程有机会执行。它不是保留原事务原子性的“暂停键”。不要在要求整体回滚的一组操作中随意调用;调用前不能先 setTransactionSuccessful(),嵌套事务也不符合该方法的安全条件。返回值表示是否实际发生了让出。

Environment.getExternalStoragePublicDirectory()——返回图片、音乐等公共目录的 File 路径,本身不授予访问权限。Android 16 源码中这个路径接口仍可用,但旧文“找到目录即可随意写入”的前提已不适用于分区存储。保存共享图片、音视频优先按 MediaStore 流程;用户选择的文档位置可使用 API 19 起的 Storage Access Framework。应用自己的内部数据继续使用应用专属目录。

View.generateViewId()——API 17 起生成可用于 setId() 的运行时 ID,避开构建工具为 R.id 分配的范围。它不会帮你识别手工重复赋值,也不是跨进程或跨重建保持不变的业务标识。需要恢复 View 状态时,要让同一控件的 ID 保持对应。

ActivityManager.clearApplicationUserData()——API 19 起允许应用请求清除自身数据,接近系统设置中的“清除存储”,不是普通退出登录。它删除应用私有数据和外部专属数据,撤销相关运行时权限等,但不卸载 APK;系统还会停止应用,见 Android 16 的服务端处理。返回 true 只表示清理请求已成功提交。普通登出应按产品需求撤销会话、清理令牌和相关账户数据,避免无差别删除用户的全部本地内容。

Context.createConfigurationContext()——API 17 起返回资源配置经过覆盖的新 Context,例如用指定 locale 读取一段资源;它不会原地修改整个应用的语言。若要支持应用级语言选择,Android 13 / API 33 有 LocaleManager,兼容旧版本可用 AppCompat 1.6.0+ 的 AppCompatDelegate.setApplicationLocales(),并遵循其 Activity 与状态保存要求。应用语言指南

ActivityOptions——API 16 起可为 Activity 启动指定动画等选项,把 toBundle() 的结果传给支持 options 的启动方法。兼容封装使用 AndroidX ActivityOptionsCompat,但不是每个新选项都能在旧系统产生相同效果。setLaunchDisplayId() 从 API 26 提供,也仍受设备多显示能力和目标显示访问规则约束。

AdapterViewFlipper.fyiWillBeAdvancedByHostKThx()——光是这个名字就很好玩:API 11 起由 AppWidgetHost 通知控件,后续翻页会由宿主调用 advance() 驱动,让控件停止自己重复推进。AOSP(Android Open Source Project)里还有 GRAVITY_DEATH_STAR_I 这样的趣味名字。

ViewParent.requestDisallowInterceptTouchEvent()——子 View 可以请求父级及祖先在当前触摸序列中不要通过 onInterceptTouchEvent() 拦截事件。父链应传递并遵守这个请求,直到 UP / CANCEL 后清除;它不能追回已经被父级拦截的事件,也不是绕过系统手势的接口。原文附的 触摸系统演讲保留为历史补充链接,本次未能重新读取。

备忘

More

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

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

关于我 && 博客

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

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

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

微信扫一扫

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