将 Kotlin 添加到现有应用

Android Studio 提供全面的 Kotlin 支持,从而让您能够将 Kotlin 文件添加到现有项目并将 Java 语言代码转换为 Kotlin 代码。然后,您可以使用 Android Studio 的所有现有工具来处理 Kotlin 代码,包括自动填充、lint 检查、重构和调试等。

如果您要开始一个新项目,并希望使用 Kotlin,请参阅创建项目

如需示例,请查看我们的 Kotlin 代码示例

将 Kotlin 添加到现有项目

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

  1. 依次点击 File > New,然后从各种 Android 模板中选择一个,例如一个新的空白 Fragment,如图 1 所示。如果您未在此菜单中看到模板列表,请先打开 Project 窗口,然后选择您的应用模块。

    创建一个新的空白 Fragment
    图 1. 从可用模板中进行选择,例如 Fragment 或 Activity。
  2. 在随即显示的向导中,选择 Kotlin 作为 Source Language。图 2 显示了当您要创建新 Activity 时使用的 New Android Activity 对话框。

    可让您选择 Kotlin 作为源语言的对话框
    图 2. New Android Activity 对话框,您可以从中选择 Kotlin 作为 Source Language
  3. 继续执行向导中的操作,直到完成。

或者,您也可以依次点击 File > New > Kotlin File/Class 来创建一个基本的 Kotlin 文件。如果您没有看到此选项,请打开 Project 窗口,然后选择 java 目录。在 New Kotlin File/Class 窗口中,您可以定义文件名并提供多种文件类型选择:FileClassInterfaceEnum ClassObject。您做出的选择决定了在新的 Kotlin 文件中为您创建的基本架构。如果您选择 Class,Android Studio 会创建一个具有给定名称和匹配类定义的新 Kotlin 源文件。如果您选择 Interface,会在文件中声明一个接口,诸如此类。

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

提示您为项目配置 Kotlin 的警告对话框
图 3. 如果没有为项目配置 Kotlin,Android Studio 会显示一个警告对话框。

出现提示时,选择用于为包含 Kotlin 文件的所有模块配置 Kotlin 的 All modules containing Kotlin files 选项,如图 4 所示:

选择为包含 Kotlin 代码的所有模块配置 Kotlin
图 4. 选择为包含 Kotlin 代码的所有模块配置 Kotlin。

在您点击 OK 后,Android Studio 会将 Kotlin 添加到项目类路径,并将 Kotlin 和 Kotlin Android 扩展插件应用于包含 Kotlin 文件的每个模块。您的 build.gradle 文件应与以下示例类似:

// Project build.gradle file.
    buildscript {
        ext.kotlin_version = '1.3.30'
        ...
        dependencies {
            classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        }
    }
    
// Inside each module using kotlin
    apply plugin: 'kotlin-android-extensions'
    apply plugin: 'kotlin-android'

    ...

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

源代码组织

默认情况下,新的 Kotlin 文件保存在 src/main/java/ 中,这样方便您在一个位置同时查看 Kotlin 文件和 Java 文件。如果您希望将 Kotlin 文件与 Java 文件分开,则可以将 Kotlin 文件放在 src/main/kotlin/ 下。如果您这样做,则还需要在 sourceSets 配置中添加此目录,如下所示:

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

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

要将 Java 代码转换为 Kotlin 代码,请在 Android Studio 中打开 Java 文件,然后依次选择 Code > Convert Java File to Kotlin File。或者,也可以创建一个新的 Kotlin 文件(依次选择 File > New > Kotlin File/Class),然后将 Java 代码粘贴到该文件中。Android Studio 随即显示一条提示,并询问您是否要将代码转换为 Kotlin 代码,如图 5 所示。点击 Yes 即可转换。您可以选择性地勾选 Don't show this dialog next time,这样会使将来的转换自动进行。

选择为包含 Kotlin 代码的所有模块配置 Kotlin
图 5. Android Studio 可将 Java 代码转换为 Kotlin 代码。

代码转换和可为 null 性

Android Studio 的转换过程会生成与编译和运行的 Kotlin 代码在功能上等效的代码。不过,您可能需要对转换后的代码进行额外的优化。例如,您可能想要优化转换后的代码如何处理可为 null 类型。

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

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,但实际上,在本例中使用时,它绝不能为 null。不过,由于在构建时没有为按钮变量赋值,因此生成的 Kotlin 代码将 Button 视为可为 null 类型,并在添加点击监听器时使用非 null 断言运算符来解封按钮,如下所示:

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 断言或安全调用运算符来解封按钮引用。

在其他情况下(根据应用的用例,null 是有效的变量赋值),将安全调用运算符 (?.) 与终止 elvis 运算符 (?:) 一起使用可能是一种更合适的方法,可以安全地解封可为 null 对象或将其强制转换为合理的非 null 默认值。在转换过程中,Android studio 没有足够的信息来做出这一决定。虽然它默认为非 null 断言,但您应不断跟进并根据需要调整转换后的代码。

更多信息

如需详细了解如何在项目中同时使用 Kotlin 代码和 Java 代码,请参阅从 Kotlin 调用 Java 代码

如需详细了解如何在企业环境中使用 Kotlin,请参阅为大型团队采用 Kotlin

如需了解现有 Android API 的惯用 Kotlin 封装容器,请参阅 Android KTX