极光日报
首发于极光日报

聊聊 Android 中的 @hide

简评:最近,XDA 中的开发者写了篇 Android 将会更严格限制「隐藏」 API 使用的文章。这里的「隐藏」是指被 @hide 标记的类和成员。这里就聊聊 Android 中的 @hide。

对于 @hide 最简单的比喻就是将 Android SDK 想象成一座冰山,在文档中的只是你能看到的部分。

Android SDK 中的类(Activity, AsyncTask, AlarmManager...)都是普通的 Java 类。因此,就可见性而言,它们受到的约束和其他 Java 类是一样的:

  • public:也就是我们在文档中能看到的大部分内容。
  • private
  • 'package-private':也就是不加限定。

对于成员,比如属性和方法,也可以是 protected,也就是对子类可见。

在理想的情况下,这些就已经足够了。

但是,这样就意味着所有 public protected 的部分都是对外可见 API 的一部分。但在某些情况下,Android 框架的开发人员需要可见性为 public 或 protected 的类或成员,但又不希望这些方法成为开发者可用的 API。

这就是 @hide 的用处了。

当你在 build.gradle 文件中指定 compileSdkVersion 为 27 时,也就是告诉了构建系统:

  • 进入 $ANDROID_SDK/platforms/android-27/ 目录。
  • 找到该目录中的 android.jar 文件。
  • 把这个 JAR 添加到编译时类路径中。

应 javac 编译你的 Java 代码时,会根据这个 android.jar 的内容来解析所有对 Android SDK 中成员的引用。但这个 android.jar 不会打包到你的应用中,而是在运行时有另一个 android.jar 被链接到应用的进程中。

编译时和运行时 android.jar 的主要区别有两点:

  • 编译时的 android.jar 不包含真正的方法实现。
  • 编译时的 android.jar 不包含被 @hide 标记的类或成员。

在 Android 8.1 版本的 Activity 中,@hide 就出现了 45 次,这还只是这一个类。

可能 Android 开发者会比较有探索精神,如果被告知不能干什么,就会有人想绕过这个限制。但使用这些方法一直是有风险的。Google 这么多年在保证 API 稳定和兼容性方面做得还不错,但这不适用于被 @hide 标记的内容。因此可能有的问题:

  • 隐藏的 API 在未来的 Android 版本中可能被删除。
  • 可能会被修改方法签名或字段类型。
  • 设备制造商还可能会删除或修改隐藏的 API,这可能会影响这部分设备。

即使没有完全禁止隐藏 API 的使用,上面的这些问题也可能在任何时候发生。因此,总的来说,普通开发者最好还是避免使用隐藏 API,风险往往大于收益。

原文:Think Hard About @hide

日报扩展阅读:

编辑于 2018-01-25

文章被以下专栏收录

    简介:每日导读(或翻译)三篇优质英文文章,内容 80% 涉及硅谷/编程/科技/,期待共同成长。