将 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 源文件和一个匹配的类定义。如果您选择**接口**,则会在文件中声明一个接口,依此类推。

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

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

出现提示时,选择为**包含 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) {
                ...
            }
        });
    }
}

即使按钮变量是可空的,但在本例中使用时,它实际上永远不应该为 null。但是,由于它的值在构造时未赋值,因此生成的 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