返回博客首页
← 所有文章

将 NativeScript 插件迁移到 AndroidX

2019 年 5 月 21 日 — 作者:Alexander Vakrilov

NativeScript 6.0 版本计划于 7 月发布,届时将支持 AndroidX。我们还将停止支持 Android Support Library,这是一个重大更改,意味着依赖它的代码应该进行迁移。

这篇博文将提供您(作为插件开发者)可以为发布做哪些准备。

重要提示:NativeScript 6 项目将在启用useAndroidXenableJetifier 的情况下构建。这意味着所有现有的库(您随附或包含在插件中的.jar.aar 文件)将在构建时由jetifier 自动迁移。

也就是说,每个 NativeScript 插件都属于以下类别之一

  1. 无需迁移插件。耶!
  2. 插件可以兼容 support-lib 和 AndroidX
  3. 没有兼容路径(或者不值得这样做)。您应该发布插件的仅 AndroidX 版本,以便使其可用于 NativeScript 6.0。

让我们看看在每种情况下推荐的处理方法。

无需迁移

示例nativescript-localstorage

如果您的插件(及其依赖项)以任何方式都不依赖于 Android Support Library - 您就不用担心了。你现在可以停止阅读了。

此外,如果插件使用依赖于 support-lib 的第三方原生库,但在 JS/TS 代码中未使用 support lib API - 很有可能您无需执行任何操作。Jetifier 会为您迁移库构建时间。当然,如果您不确定,最好还是进行测试。

版本控制

在这种情况下,无需发布插件的新版本。

使其与 Support-lib 和 AndroidX 兼容

示例nativescript-permissions

在许多情况下,可以通过执行运行时检查以了解哪个可用,从而使您的插件与 support-lib AndroidX 兼容。

在某些情况下,重写代码以使其兼容将需要更多努力。主要是在扩展support lib 中的类时。以下是如何执行此操作的示例

function useAndroidX {
    return global.androidx && global.androidx.appcompat;
};

function getMyClass() {
    if (useAndroidX()) {
        // Class implementation using AndroidX
        class MyCardView extends androidx.cardview.widget.CardView {
            // implementation skipped for brevity 
        }

        return MyCardView;
    } else {
        // Class implementation using support-lib
        class MyCardView extends android.support.v7.widget.CardView {
            // implementation skipped for brevity 
        }    

        return MyCardView;
    }
}

// Get the final class
const MyCardViewClass = getMyClass();

什么?!但是,我有很多问题!

是的!上面的代码看起来很奇怪。让我们尝试解决一些问题。

1. 静态绑定生成器 (SBG) 如何知道要为哪两个实现生成绑定?

SBG 将尝试为两者生成绑定。但是,它只会成功生成扩展其在构建时知道的类的实现的绑定(您在 Android 项目中引用的库)。因此,如果您正在为 NativeScript 5 构建 - 它将在其上下文中包含 support-lib,并将设法生成一个扩展android.support.v7.widget.CardView 的类。它不会为扩展androidx.cardview.widget.CardView 的实现生成绑定。在为 NativeScript 6 构建时,情况正好相反。useAndroidX() 检查将确保您在运行时使用正确的实现。

重要提示:SBG 将直接匹配extends 中的类。因为它实际上并没有评估 JS 代码,所以您不能在那里放置动态代码。因此,以下将不起作用

const supportLib = global.androidx ? androidx.cardview.widget : extends android.support.v7.widget;
class MyCardView extends supportLib.CardView { ... }

2. 看起来有很多重复的代码?

您可以尝试通过将一些代码提取到类的实现之外来共享这些代码。但是……是的,您的代码会变得不那么漂亮。

3. TypeScript 定义呢?

您可以使用tns-platform-declarationsandroidx 标记来获取 AndroidX 类型(npm i tns-platform-declarations@androidx)。它将为您提供 AndroidX 中类型的定义,但您不会获得 support-lib 的定义。您可能希望使用<any> 或“存根”来表示其中一种风格(例如declare var androidx:any;)。

版本控制

完成迁移后,您可以安全地将这些更改发布为插件的次要或修补程序版本。好消息是您现在可以这样做,并且您的插件在发布时将可用于 NativeScript 6。

没有兼容路径

示例tns-core-modules

您的插件可能无法与 support-lib 和 AndroidX 兼容。这可能是由于多种原因造成的

  • Java 代码或第三方库依赖于 support-lib(并且由于某种原因 jetifier 无法处理它)。
  • 您在 JS 代码中扩展了 support-lib 类,并且不想用 androix 运行时检查来膨胀您的代码。
  • 您在android-manifest.xml 或其他资源中具有 support lib 配置,而 jetifier 无法处理这些配置。

有一些工具可以帮助您进行迁移。您可以使用jetifier-standalone 工具 用于原生依赖项和/或androidx-migration-tool 用于您的 JS/TS/Java 代码。您还可以查看NativeScript 中对 AndroidX 的支持,了解有关迁移的提示

版本控制

以下是推荐的操作计划

  1. 迁移插件。
  2. 将主要版本号提升并将其发布到 npm 中的androidx 标记后面:$npm publish --tag androidx
  3. (在 NativeScript 6.0 发布时)发布 AndroidX 版本。最好添加对"tns-core-modules": ">6.0.0" 的 peerDependency。

注意:在正式发布 NativeScript 6 之前,在androidx 标记后面发布将使其他依赖它的插件和应用程序有机会进行测试。

立即测试您的插件!

无论您的插件属于哪个类别,都强烈建议您现在使用 android-runtime 和 tns-core-modules 的androidx 构建进行测试

npm install tns-core-modules@androidx --save-exact
tns platform add android@androidx
npm install tns-platform-declarations@androidx --save-exact (if you need typings)

然后,您可以运行演示项目以确保一切按预期工作。

获取帮助

处理重大更改可能很繁琐,但我们随时为您提供帮助。如果您遇到问题,请在NativeScript Slack - #androidx-migration 频道 中联系我们。