写点什么

当支付宝 App 遇见 AndroidX......

发布于: 4 小时前
当支付宝 App 遇见 AndroidX......

作者:扬州


本文主要介绍支付宝 Android 端拥抱 AndroidX 过程中的一些新(xin)鲜(suan)事(lei),通过文章可以了解到以下内容:


  • 支付宝升级到 AndroidX 有何不同/难点?

  • Android Studio 的 Migrate AndroidX 是如何实现的?

  • APK 产物怎么适配 AndroidX?

背景

自 2018 年 Android Support 被“革了命”后,Support 扩展库被尘封,享年 28(最后的一个官方版本)。而 AndroidX 得到了社区的广泛接纳,众多知名框架纷纷推出 AndroidX 适配的版本,各大 App 厂家也跟进 AndroidX 升级。


不负责任的说,缺失 AndroidX 长远来看将与 Android 社区组件脱节,无法享受到组件的维护,新的组件也难以融入,比如 Paging 3.0,CameraX 1.0.0,Hilt 1.0.0,AppSearch 1.0.0,更不用说后起新秀 Jetpack Compose。

AndroidX 业内情况

这里不细数 AndroidX 的内容,一句话概括:AndroidX 是 Support 的接班人,承接了原有 Support 28 的功能,并且持续迭代出了更多的扩展库。


通过查看某应用市场,榜单 50 的 App 软件包,分析这些 APK 的 AndroidX 适配情况,我们得到了一个数据,目标群体排序前 50 的有 70%适配了 AndroidX(列表并不权威,不必过于关注排名):

应用宝列表:分类页面 - 应用首页


业内 App 适配 AndroidX 情况还是比较好的,虽然抽样有 70%适配了,那剩下的也有 30%,而且都是体量靠前的 App。


读到这儿,你可能就要问了:为什么还有多应用还没有适配?


在软件开发中经常会提到“技术债”,也就是说每次面临系统重大调整,对研发人员都是一种考验。具体到每个独立的 App,架构差异、业务研发模式、组件使用诉求、研发饱和情况等,都会形成升级的阻力。


那么,同样会面临以上阻力的支付宝 App,遇见 AndroidX,会擦出怎样的“火花”?

钱包适配 AndroidX

为了让庞大的支付宝 App 顺利披上 AndroidX 的战袍,我们需要设计一个技术方案,能够灵活和众多业务进行适配工作,有意愿和诉求的业务,进行深度源码适配;暂时“实力不允许”的业务,我们想办法提供兜底的方案。

AndroidX 适配点

适配 AndroidX,通过分析方案,我们知道主要处理以下内容:


  1. Java/Class 源码,各种 support 的类,包替换

  2. xml 布局,替换 support 组件名字

  3. build.gradle,修改 dependency 中的 GAV

  4. proguard,混淆规则替换

  5. pom 依赖,dependency 处理

钱包架构现状

蚂蚁的 Android 开发对支付宝的构建体系都非常熟悉,他与原生是有一些差异的。这里我们简单做个抽象,以便非蚂蚁的 Android 开发能快速了解一个全貌。


从项目的构建上来看,我们可以画出两张图,我给取名分别是:“传统 Android 开发”,“支付宝 Android 开发”。这里不讨论 Android 的插件化(这几乎是国内特有的风气)。



PS:这里没有涵盖 Google Play 2021.8 月即将强推的 AAB 上架方案,感兴趣的同学可以自己脑补下大图。



对比两张图,主要区别在用 AGP 构建的差异,mPaas 目前也是钱包体系商业化的一个输出。依托于深度的构建定制,结合钱包的运行时框架,我们充分的实现了业务的并行开发和和动态交付能力。如果要用几个简单的词汇来描述,我会这样表述:


  • 业务隔离 =》Bundle

  • 构建分离 =》mPaas+Bundle

  • 产物聚合,动态发布 =》mPaas+Portal+Bundle


这个体系优点很多,前人种树后人乘凉,但是也需要承担深度定制后遗留的痛点和坑位。


了解完了 AndroidX 的适配点和钱包的开发模式,你因该能猜到,钱包要适配 AndroidX 的遇到的第一个问题:适配需要 Java 源码或者 Class 字节码的修改,而钱包中业务是通过 APK 隔离的,几乎没有 AAR。

阻力与动力

在支付宝这边,对于 Android 开发来说,我们是有对标原生开发的,包括研发效能,编译链对齐等。


我们升级 AndroidX 的阻力包括:


  • Support 类库广泛使用,API 兼容性挑战;

  • 众多跨团队模块,改一下就是“百团大战”;

  • 官方升级机制不适用,不适用钱包的构建;

  • 布局动态容器,存在冲突。


动力也不少(不分先后):


  • Android Support 已不再维护;

  • AndroidX 社区融入度提升;

  • 现代 Android 开发基于 AndroidX;

  • 业务上有使用的诉求。


在多次的沟通和调整后,我们的研究的方案几个点要保证:


  • 关联方尽量少;

  • 兼容能力;

  • 侵入性小;

  • 可插拔的适配。


不能要求所有业务开发一起源码适配 AndroidX,否则你可能会问自己:我是谁?我在哪?我要干什么?


需要兼容本身就很少迭代的历史模块,比如 16 年开始的就没有变更的模块,你要找人配合是不是现实?


站在业务开发的立场,适配不要比官方方案更复杂,尽量做到无感知适配。适配能力向 Andoird 靠拢,提供开关,方便业务选择性处理。

钱包适配实现

这里是一张早先绘制的,在构建中适配 AndroidX 的流程和卡点。



类替换


Java/Class 代码处理是针对与源码工程和 AAR 的,钱包的 bundle 是 apk,内部是编译后的 dex 和二进制 xml。在类替换环节,我们通过解析 dex 文件结构,将 support 替换集合中的映射关系逐一修改到 dex 中。


xml 替换


apk 中的 xml 是二进制的的 plain 格式,他不是文本文件,有自己的格式。这个格式简单来说就是 Chunk,我们找到其中的存放的 xml node 节点,把节点对应的值运用 support 替换集合,修改完后重新保存为二进制的 xml。


Bundle 替换


结合前面两个步骤,得到一个新的 apk。替换 dependency 中的 bundle/devbundle 依赖。


产物


当我们对一个业开启适配后,他的产物会发生变化。




修改完成后,我们会输出一份 txt 报告,共开发者检查使用,这里有一份示例:


OLD: /Users/█████/work/android-phone-█████-git/build/build/outputs/apk/debug/█████-build-debug.apkNEW: /Users/█████/work/android-phone-█████-git/build/build/bundle-cache/█████-build-debug.apk
class count: 53xml count: 1
===================== DEX =====================
* com/alipay/android/█████/█████/█████ (3)* com/alipay/android/█████/██████████$█████ (3)* com/alipay/mobile/██████████/███/██████████$12 (9)* com/alipay/mobile/█████/█/█████ (45)* com/alipay/mobile/██/██/█████$██████████ (28)* com/alipay/mobile/█/███/███████████████ (3)* com/alipay/android/█████/█████/███████ (3)* com/alipay/mobile/██████/█/██████$████ (9)* com/alipay/mobile/███/███/█████████ (13)* com/alipay/android/███/██/█████ (20)* com/alipay/mobile/███/█/████$█████ (9)* com/alipay/android/███/█████████$█████ (12)* com/alipay/mobile/██/█/██████████████ (27)* com/alipay/mobile/█/███/███████████████ (3)* com/alipay/mobile/██/██/█████/████████ (9)* com/alipay/android/██/█/██████████████████ (6)* com/alipay/mobile/█/███/███████████████ (3)* com/alipay/android/█████/███/██████ (23)* com/alipay/android/██/██/████████████ (30)* com/huawei/android/█████/████████$███████████ (2880)* com/alipay/android/████/██████$14 (4)* com/alipay/android/█████/██/█████████ (41)* com/alipay/android/████/████/██████████████████ (129)* com/alipay/android/████/████████████ (22)* com/alipay/android/████████/███████/█████████████████ (3)* com/alipay/mobile/████/██████/███████/█████████████████████████ (3)* com/alipay/android/████████/████/███████████████ (18)* com/alipay/mobile/████████/███/████████████████████████ (27)* com/alipay/android/████████/██████████████████$21 (17)* com/alipay/mobile/██████/██████/████████████████████████████████$██████████████████████ (6)* com/alipay/android/████████/██████████████████$22 (8)* com/alipay/mobile/████████/███/██████████████████$5 (9)* com/alipay/android/████████/██████████████████$20 (6)* com/alipay/android/████████/████/█████████████ (23)* com/alipay/mobile/██████/██████/██████████████████████████$4 (3)* com/alipay/mobile/██████/██████/████████████████████████████████$████████████████████ (38)* com/alipay/mobile/██████/██████/██████████████████████████$2 (4)* com/alipay/mobile/██████/██████/██████████████████████████$8 (6)* com/alipay/android/████████/██████████████████ (293)* com/alipay/mobile/██████/██████/██████████████████████████$6 (3)* com/alipay/mobile/██████/██████/█████████/███████████████$5 (9)* com/alipay/android/████/████████████$1$1 (11)* com/alipay/mobile/██████/██████/████████████████████████████████ (87)* com/alipay/android/████████/█████/██████████████████████ (7)* com/alipay/android/████████/tab/█████████████████$2 (4)* com/alipay/android/████████/tab/█████████████████$1 (4)* com/alipay/mobile/██████/██████/████████████████████████████████$2$1 (7)* com/alipay/android/████/████████████$1 (5)* com/alipay/android/████████/████/███████████████$████████████████████$1$1 (9)* com/alipay/mobile/████████/███/████████████$5 (9)* com/alipay/mobile/████/████████/█████████████████████ (2)* com/alipay/mobile/████████/███/████████████████████████$4 (9)* com/alipay/mobile/██████/██████/██████████████████████████ (306)
Reference detail:* com/alipay/android/████████/█████/█████████████████████ (3) | android/support/annotation/NonNull -> androidx/annotation/NonNull (3)
* com/alipay/android/████████/██████████████████$█████████████ (3) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (3)
* com/alipay/mobile/████████/███/████████████$12 (9) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (9)
* com/alipay/mobile/████████/███/████████████ (45) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (45)
* com/alipay/mobile/██████/██████/██████████████████████████$LoginActivityOnWindowsFocusChangeReceiver (28) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (9) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (19)
* com/alipay/mobile/████/██████/█████████████████████████ (3) | android/support/annotation/NonNull -> androidx/annotation/NonNull (3)
* com/alipay/android/████████/███████/████████████ (3) | android/support/annotation/Nullable -> androidx/annotation/Nullable (3)
* com/alipay/mobile/████████/███/████████████$█████████████ (9) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (9)
* com/alipay/mobile/██████/██████/██████████████████████ (13) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (10) | android/support/annotation/NonNull -> androidx/annotation/NonNull (3)
* com/alipay/android/████████/████/████████████████████████ (20) | android/support/v4/app/FragmentPagerAdapter -> androidx/fragment/app/FragmentPagerAdapter (3) | android/support/v4/app/FragmentManager -> androidx/fragment/app/FragmentManager (11) | android/support/v4/app/Fragment -> androidx/fragment/app/Fragment (6)
* com/alipay/mobile/████████/███/████████████████████████$█████████████ (9) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (9)
* com/alipay/android/████████/██████████████████$TabChangeTimeRunnable (12) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (12)
* com/alipay/mobile/████████/███/██████████████████ (27) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (27)
* com/alipay/mobile/base/config/ConfigServiceLmacSyncCallback (3) | android/support/annotation/NonNull -> androidx/annotation/NonNull (3)
* com/alipay/mobile/██████/██████/█████████/███████████████ (9) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (9)
* com/alipay/android/████████/████/█████████████████████████████████████████ (6) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (6)
* com/alipay/mobile/█████/█████/████████████████████ (3) | android/support/annotation/NonNull -> androidx/annotation/NonNull (3)
* com/alipay/android/████████/████/███████████████ (23) | android/support/v4/app/Fragment -> androidx/fragment/app/Fragment (7) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (16)
* com/alipay/android/████████/████/████████████████████ (30) | android/support/v4/view/ViewPager -> androidx/viewpager/widget/ViewPager (18) | android/support/v4/app/FragmentManager -> androidx/fragment/app/FragmentManager (7) | android/support/v4/view/PagerAdapter -> androidx/viewpager/widget/PagerAdapter (5)
* com/huawei/android/██████████/███████████████$████████████████████ (2880) | android/support/v4/view/ViewPager -> androidx/viewpager/widget/ViewPager (277) | android/support/v4/app/FragmentManager -> androidx/fragment/app/FragmentManager (166) | android/support/v4/app/Fragment -> androidx/fragment/app/Fragment (270) | android/support/v4/view/PagerAdapter -> androidx/viewpager/widget/PagerAdapter (92) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (1018) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (542) | android/support/v4/view/ViewPager$OnPageChangeListener -> androidx/viewpager/widget/ViewPager$OnPageChangeListener (105) | android/support/v4/app/FragmentTransaction -> androidx/fragment/app/FragmentTransaction (144) | android/support/v4/util/ArrayMap -> androidx/collection/ArrayMap (106) | android/support/v4/app/FragmentPagerAdapter -> androidx/fragment/app/FragmentPagerAdapter (52) | android/support/v4/content/ContextCompat -> androidx/core/content/ContextCompat (48) | android/support/annotation/Nullable -> androidx/annotation/Nullable (26) | android/support/annotation/NonNull -> androidx/annotation/NonNull (34)
* com/alipay/android/████████/██████████████████$14 (4) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (4)
* com/alipay/android/████████/tab/█████████████████ (41) | android/support/v4/util/ArrayMap -> androidx/collection/ArrayMap (41)
* com/alipay/android/████████/████/██████████████████ (129) | android/support/v4/view/ViewPager -> androidx/viewpager/widget/ViewPager (69) | android/support/v4/view/ViewPager$OnPageChangeListener -> androidx/viewpager/widget/ViewPager$OnPageChangeListener (39) | android/support/v4/view/PagerAdapter -> androidx/viewpager/widget/PagerAdapter (21)
* com/alipay/android/████/████████████ (22) | android/support/v4/app/Fragment -> androidx/fragment/app/Fragment (5) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (14) | android/support/annotation/Nullable -> androidx/annotation/Nullable (3)
* com/alipay/android/████████/███████/█████████████████ (3) | android/support/annotation/Nullable -> androidx/annotation/Nullable (3)
* com/alipay/mobile/████/██████/███████/█████████████████████████ (3) | android/support/annotation/NonNull -> androidx/annotation/NonNull (3)
* com/alipay/android/████████/████/███████████████ (18) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (18)
* com/alipay/mobile/████████/███/████████████████████████ (27) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (27)
* com/alipay/android/████████/██████████████████$21 (17) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (17)
* com/alipay/mobile/██████/██████/████████████████████████████████$██████████████████████ (6) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (6)
* com/alipay/android/████████/██████████████████$22 (8) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (8)
* com/alipay/mobile/████████/███/██████████████████$5 (9) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (9)
* com/alipay/android/████████/██████████████████$20 (6) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (6)
* com/alipay/android/████████/████/█████████████ (23) | android/support/v4/view/ViewPager$OnPageChangeListener -> androidx/viewpager/widget/ViewPager$OnPageChangeListener (7) | android/support/v4/view/ViewPager -> androidx/viewpager/widget/ViewPager (16)
* com/alipay/mobile/██████/██████/██████████████████████████$4 (3) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (3)
* com/alipay/mobile/██████/██████/████████████████████████████████$████████████████████ (38) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (29) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (9)
* com/alipay/mobile/██████/██████/██████████████████████████$2 (4) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (4)
* com/alipay/mobile/██████/██████/██████████████████████████$8 (6) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (6)
* com/alipay/android/████████/██████████████████ (293) | android/support/v4/app/Fragment -> androidx/fragment/app/Fragment (23) | android/support/v4/util/ArrayMap -> androidx/collection/ArrayMap (3) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (184) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (77) | android/support/annotation/Nullable -> androidx/annotation/Nullable (6)
* com/alipay/mobile/██████/██████/██████████████████████████$6 (3) | android/support/annotation/Nullable -> androidx/annotation/Nullable (3)
* com/alipay/mobile/██████/██████/█████████/███████████████$5 (9) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (9)
* com/alipay/android/████/████████████$1$1 (11) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (11)
* com/alipay/mobile/██████/██████/████████████████████████████████ (87) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (69) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (18)
* com/alipay/android/████████/█████/██████████████████████ (7) | android/support/annotation/NonNull -> androidx/annotation/NonNull (7)
* com/alipay/android/████████/tab/█████████████████$2 (4) | android/support/v4/util/ArrayMap -> androidx/collection/ArrayMap (4)
* com/alipay/android/████████/tab/█████████████████$1 (4) | android/support/v4/util/ArrayMap -> androidx/collection/ArrayMap (4)
* com/alipay/mobile/██████/██████/████████████████████████████████$2$1 (7) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (7)
* com/alipay/android/████/████████████$1 (5) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (5)
* com/alipay/android/████████/████/███████████████$████████████████████$1$1 (9) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (9)
* com/alipay/mobile/████████/███/████████████$5 (9) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (9)
* com/alipay/mobile/████/████████/█████████████████████ (2) | android/support/v4/content/ContextCompat -> androidx/core/content/ContextCompat (2)
* com/alipay/mobile/████████/███/████████████████████████$4 (9) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (9)
* com/alipay/mobile/██████/██████/██████████████████████████ (306) | android/support/v4/app/FragmentActivity -> androidx/fragment/app/FragmentActivity (202) | android/support/v4/content/LocalBroadcastManager -> androidx/localbroadcastmanager/content/LocalBroadcastManager (22) | android/support/v4/app/FragmentManager -> androidx/fragment/app/FragmentManager (36) | android/support/v4/app/FragmentTransaction -> androidx/fragment/app/FragmentTransaction (38) | android/support/v4/app/Fragment -> androidx/fragment/app/Fragment (8)
===================== XML =====================
* res/layout/███████████████.xml (1)
Reference detail:* res/layout/███████████████.xml (1) | android.support.v4.view.ViewPager -> androidx.viewpager.widget.ViewPager
复制代码


基于 apk 进行 androidx 适配的能力,我们封装为了一个独立的 jar 工程,既可以集成到 Gradle Plugin 中使用,也可以发布为命令行工具使用。下面介绍下命令行的使用:


bx --input=src/test/resources/█████ .apk --output=build/intermediate
复制代码


user % bx --help    ___              __           _     ___  __   /   |  ____  ____/ /________  (_)___/ / |/ /  / /| | / __ / __  / ___/ __ / / __  /|   /  / ___ |/ / / / /_/ / /  / /_/ / / /_/ //   |  /_/  |_/_/ /_/__,_/_/   ____/_/__,_//_/|_|                                                 Translate apk to compat with AndroidX dependency.Usage: bx [OPTIONS] [ARGS]...
Options: --help 显示帮助信息 --input 待处理apk路径, 示例: --input=input.apk --output 处理后产物目录, 示例: --output=output-dir --clean 清理中间生成物, 示例: --clean=true --verbose 输出调试的日志, 示例: --verbose=true --jetify 使用jetify处理, 示例: --jetifye=true
复制代码


构建平台打包,根据包类型不同,所需要编译的工程模块,插件逻辑如覆盖率插桩等,都有差异。因此不同类型的构建整体耗时有差异。androidx 的增量耗时主要源自于集中式的转义的模块体量,随着独立适配模块数量的增加,集中耗时将逐步减少,根据数据采集分析,目前做一次全量的转义消耗时间比较稳定。最终理想情况是总包的构建基本不增加额外耗时。


将 bx 运用到钱包的构建插件后,可基于 portal 基线做批量的 bundle 兼容。开启兼容能力后,对整体构建时间有一定增量,通过持续优化可以逐步减少增量耗时。



原生的适配

Google 本身提供了一天真对 aar 的适配方案,这部分可以直接上手。该套方案有三种使用方式:


  • 一是通过 AS 的 Migrtate AndroidX,这要求 AGP 版本为 3.2.0 或更高;

  • 二是通过命令行,单独执行 jar 应用程序,这与上下文无关;

  • 三是源码改造,参考 AGP 的内部实现,去联动 Jetify 模块。


./jetifier-standalone -i <source-library> -o <output-library>
复制代码


关于 Jetify 的介绍,这里摘录了一段文档说明:


Jetifier 会迁移指向 android.support.* 软件包的 Java、XML、POM 和 ProGuard 引用,更改它们以使其指向相应的 androidx.* 软件包。

由于 android.support.* 的 ProGuard 通配符并不总是直接映射到 androidx.* 软件包,因此 Jetifier 会生成所有符合条件的替代项。

如果 android.support.* 软件包中的某个类型不是来自任何支持库工件,那么只要该类型存在相关的映射,Jetifier 就会迁移该类型。但是,不能保证此迁移一定可行,因为可能没有足够通用的映射规则来涵盖所有自定义类型。


这个工具甚至可以反向执行,把 androidx 产物转位 supportg 产物,感兴趣可以试一下,-r 参数。


在 AS 中,我们开启 gradle 参数配置后可以激活 jetify 机制,这个机制会对 dependency 依赖进行预处理,将依赖了 support 扩展库的 aar 编译为 androidx 版本。


android.useAndroidX=trueandroid.enableJetifier=true
复制代码


具体到代码实现,则是利用了 Gradle 的 Artifact Transform 机制,对依赖的 aar 文件拆解处理。相关源码可以参考:com.android.build.gradle.internal.dependency.JetifyTransform


这个 transform 中,最终会调用前面提到的 jetify 工具,Google 将工具做成了独立的 maven 依赖:


androidx.jetifier:jetifier-core:1.0.0-beta10


https://developer.android.com/jetpack/androidx/releases/jetifier

后续

目前支付宝 App 已经完成的大部分业务的适配工作,部分有侵入性使用 Support 扩展库,如反射实例化 View 的需要业务进行适配。方案灰度也在持续推进当中。


除了 AndroidX 之外,我们也在推进 Kotlin,Java8 等在钱包构建体系的落地,期待钱包在完成 AndroidX 升级之后,全业务可以向原生化,现代 Android 开发更近一步。



欢迎也在积极拥抱 AndroidX 的小伙伴们,一起留言交流,共同探讨适配 AndroidX 的经验/教训。


关注我们,每周 3 篇移动技术实践 &干货给你思考!

发布于: 4 小时前阅读数: 3
用户头像

还未添加个人签名 2018.07.07 加入

阿里巴巴移动&终端技术官方账号。

评论

发布
暂无评论
当支付宝 App 遇见 AndroidX......