在现有应用中添加 Kotlin

Android Studio 提供了 对 Kotlin 的全面支持,使您能够将 Kotlin 文件添加到现有项目中并将 Java 语言代码转换为 Kotlin。然后,您可以将 Android Studio 的所有现有工具与您的 Kotlin 代码一起使用,包括自动完成、Lint 检查、重构、调试等。

如果您要启动新项目并希望使用 Kotlin,请参阅 创建项目

有关示例,请查看我们的 Kotlin 代码示例

将 Kotlin 添加到现有项目

要将 Kotlin 添加到您的项目,请执行以下操作

  1. 点击 **文件 > 新建**,然后选择各种 Android 模板之一,例如新的空白 **片段**,如图 1 所示。如果您在该菜单中没有看到模板列表,请先打开 **项目** 窗口,然后选择您的应用模块。

    create a new blank fragment
    图 1. 从可用的模板中选择,例如片段或活动。
  2. 在出现的向导中,为 **源语言** 选择 **Kotlin**。图 2 显示了 **新建 Android 活动** 对话框,用于创建新的活动。

    dialog that lets you choose Kotlin for your source language
    图 2. 新建 Android 活动 对话框,您可以在其中选择 Kotlin 作为您的 源语言
  3. 继续完成向导。

或者,您可以点击 **文件 > 新建 > Kotlin 文件/类** 以创建基本的 Kotlin 文件。如果您没有看到此选项,请打开 **项目** 窗口并选择 **java** 目录。**新建 Kotlin 文件/类** 窗口允许您定义文件名,并为文件类型提供多种选择:**文件**、**类**、**接口**、**枚举类** 或 **对象**。您所做的选择将决定在新的 Kotlin 文件中为您创建的基本脚手架。如果您选择 **类**,Android Studio 将创建一个新的 Kotlin 源文件,其中包含给定的名称和匹配的类定义。如果您选择 **接口**,则在文件中声明一个接口,依此类推。

如果这是您第一次直接(不使用 Android 模板)将新的 Kotlin 类或文件添加到项目中,Android Studio 会显示一条警告,表明 Kotlin 在项目中没有配置,如图 3 所示。通过点击编辑器右上角或弹出窗口的右下角的 **事件日志警报** 中的 **配置** 来配置 Kotlin。

warning dialog that prompts you to configure Kotlin for your
      project
图 3. Android Studio 在 Kotlin 未配置到您的项目时会显示警告对话框。

在出现提示时,选择在 **包含 Kotlin 文件的所有模块** 中配置 Kotlin,如图 4 所示

choose to configure Kotlin for all modules that contain Kotlin code
图 4. 选择为包含 Kotlin 代码的所有模块配置 Kotlin。

单击 **确定** 后,Android Studio 会将 Kotlin 添加到您的项目类路径,并将 Kotlin Android 插件应用于包含 Kotlin 文件的每个模块。您的 build.gradle 文件应该类似于以下示例

Groovy

// Project build.gradle file.
buildscript {
    ext.kotlin_version = '1.4.10'
    ...
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

Kotlin

// Project build.gradle.kts file.
buildscript {
    extra["kotlin_version"] = "1.4.10"
    ...
    dependencies {
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
    }
}

Groovy

// Inside each module using kotlin
plugins {
    ...
    id 'kotlin-android'
}

...

dependencies {
    implementation 'androidx.core:core-ktx:1.3.2'
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}

Kotlin

// Inside each module using kotlin
plugins {
    ...
    kotlin("android")
}

...

val kotlin_version: String by rootProject.extra

dependencies {
    implementation("androidx.core:core-ktx:1.3.2")
    implementation("org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version")
}

源代码组织

默认情况下,新的 Kotlin 文件将保存在 src/main/java/ 中,这使得在一个位置轻松查看 Kotlin 和 Java 文件。如果您希望将 Kotlin 文件与 Java 文件分开,则可以将 Kotlin 文件放在 src/main/kotlin/ 下。如果您这样做,那么您还需要在 sourceSets 配置中包含此目录,如下所示

Groovy

android {
    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }
}

Kotlin

android {
    sourceSets {
        getByName("main") {
            java.srcDir("src/main/kotlin")
        }
    }
}

将现有的 Java 代码转换为 Kotlin 代码

要将 Java 代码转换为 Kotlin,请在 Android Studio 中打开 Java 文件,然后选择 **代码 > 将 Java 文件转换为 Kotlin 文件**。或者,创建一个新的 Kotlin 文件(**文件 > 新建 > Kotlin 文件/类**),然后将您的 Java 代码粘贴到该文件中。然后,Android Studio 会显示一个提示,并提供将代码转换为 Kotlin 的选项,如图 5 所示。点击 **是** 转换。您可以选择选中 **下次不再显示此对话框**,这将使以后的转换自动进行。

choose to configure Kotlin for all modules that contain Kotlin code
图 5. Android Studio 可以将 Java 代码转换为 Kotlin。

代码转换和可空性

Android Studio 的转换过程会生成功能上等效的 Kotlin 代码,这些代码可以编译和运行。但是,您可能需要对转换后的代码进行额外的优化。例如,您可能希望细化转换后的代码处理可空类型的方式。

在 Android 中,通常会延迟初始化 View 对象和其他组件,直到它们所附加的片段或活动达到适当的生命周期状态。例如,您可能在其中一个片段中引用了一个按钮,如以下代码片段所示

public class JavaFragment extends Fragment {

    // Null until onCreateView.
    private Button button;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_content, container,false);

        // Get a reference to the button in the view, only after the root view is inflated.
        button = root.findViewById(R.id.button);

        return root;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // Not null at this point of time when onViewCreated runs
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ...
            }
        });
    }
}

即使按钮变量是可为空的,但在本示例中使用时,它在实际应用中永远不应该为空。但是,由于其值在构造时没有赋值,生成的 Kotlin 代码将 Button 视为可为空类型,并在添加点击监听器时使用非空断言运算符来解开按钮,如下所示

class JavaFragment : Fragment() {

    // Null until onCreateView.
    private var button: Button? = null

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?): View? {
        ...
        // Get a reference to the button in the view, only after the root view is inflated.
        button = root.findViewById(R.id.button)
        ...
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // Not null at the point of time when onViewCreated fires 
        // but force unwrapped nonetheless
        button!!.setOnClickListener { }
    }
}

这种转换不如在本例中使用 lateinit 理想,因为您必须在访问按钮引用时使用非空断言运算符或安全调用运算符来解开它。

在其他情况下,如果根据应用程序的用例,null 是一个有效的变量赋值,则使用安全调用 (?) 运算符和终止的 Elvis 运算符 (?:) 运算符可能是安全地解开可为空对象或强制转换为合理非空默认值的更合适方法。Android Studio 在转换过程中没有足够的信息来做出此判断。虽然它默认为非空断言,但您应该跟进并根据需要调整转换后的代码。

更多信息

有关在项目中使用 Kotlin 和 Java 代码的更多信息,请参阅 从 Kotlin 调用 Java 代码

有关在企业场景中使用 Kotlin 的更多信息,请参阅 为大型团队采用 Kotlin

有关现有 Android API 的惯用 Kotlin 包装器的信息,请参阅 Android KTX