Kotlin从0到开发一个 App — Part 2:语法,空安全,静态类型

1,217 阅读5分钟

在这个部分,我们将理解这个语言的一些基本概念,添加一些代码到 MainActivity.kt中.

目前已完成内容:

Kotlin — Part 0:关于这个系列
Kotlin — Part 1:配置 Android Studio
Kotlin — Part 2:语法,空安全,静态类型
Kotlin — Part 3:扩展函数、Android 扩展、委托属性
Kotlin — Part 4:RecyclerView— Kotlin 适配器委托&数据类
Kotlin — Part 5:Kotlin,RxJava&RxAndroid
Kotlin — Part 6:API-Retrofit&Kotlin)
Kotlin — Part 7:无限滑动:高阶函数& Lambdas

待完成:

Kotlin — Part 8:方向改变(序列化&数据类)
Kotlin — Part 9: Kotlin Unit 测试(Mockito,RxJava&Spek)
Kotlin — Part 10:Kotlin&Dagger2(依赖注入)
Kotlin — Part 11:Kotlin 持续集成

Github 仓库:github.com/imuhao/Kedd…

Kotlin 语法

现在我们准备好开始学习一些语法,当你第一眼看到这些代码你可能会有一些恐惧,但是相信我会让你喜欢它.

Kotlin 是一个简洁,安全,静态类型,可以与 Java 相互操作的程序语言

我们回顾刚刚插件自动生成的代码,在这将给你两个 MainActivity 文件: Java 和 Kotlin 文件.

MainActivity. java(转换前的代码)

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }

MainActivity.kt(转换后的代码)

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val toolbar = findViewById(R.id.toolbar) as Toolbar
        setSupportActionBar(toolbar)
        val fab = findViewById(R.id.fab) as FloatingActionButton
        fab.setOnClickListener { view -> Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG).setAction("Action", null).show() }
    }
}

简洁

你有没有注意到 Java 文件有19行代码, Kotlin 文件只有12行?

这是因为大多数冗长的 java 代码被消除,简洁的代码将花费更少的时间编写和阅读.这将改善你的生产力.

继承和实现

extends“和” implement“单词已经被一个冒号”:“取代.在这种情况下我们从 AppCompatActivity 下继承.

class MainActivity : AppCompatActivity()

####Fun — 关键字

我们不需要我们的类存在”public void methodName()“结构.现在我们在使用”fun“关键字,在类中定义一个函数.返回的类型添加在结尾.

override fun onCreate(savedInstanceState: Bundle?)

但是我们 onCreate方法的返回类型在哪里?

在 Java 中如果我们不需要返回任何值使用” void”,在这里我们使用” Unit”替代,编译器将知道我们不需要返回任何东西,所以我们可以省略它,在这种情况下我们使用下面的方式添加.

override fun onCreate(savedInstanceState: Bundle?):Unit

参数的顺序将发生改变,首先你需要定义参数的名字,之后是类型

分号再见

在 Kotlin 中你不需要在代码的结尾添加”;”分号,但是你也可以添加(建议不要)

值和变量

定义一个变量使用” var“关键字,它的类型会在上下文中推断出来,另一个相同的常量使用” val“关键字

val price = 100        // Int
price = 30             // don't compile! it's a constant
var total = price * 3  // Int
val name = "Juancho"   // String

你可以显示的指定类型

val lastname : String = "Keddit" // explicit type definition
var size : Double = 30.0
var time : Float = 15f

你可以注意到没有原始类型,我们不使用” double”而是” Double”.这是因为 Kotlin 中任何事物都是对象.为了提高性能,编译器在内部将转换一些对象到原始类型.

属性和字段

在 Kotlin 你访问属性,像在 Java 中访问字段.而不是从Activity调用它的 getResources() 方法.

resources.getString(R.string.id)
// vs
getResources().getString(R.string.id) // still allowed

你可以仍然调用 getResult() 方法,但是 Android Studio 建议你改变它.

这不以为这你直接访问这个字段,在内部它也是调用” getResource()”方法,但是这是更方便的方法.

Safe?:Safe!

这是一个在Kotlin 中伟大的事情,在 Kotlin 中没有可以为空的,除非你使用这个方法特别指定它,这个方法是使用”?

val a : String = null  // 不会编译!
var b : Int          // 必须初始化,或者抽象
val ok : String? = null // 正确 :)

编译器将检测可能为空的对象,这将使你避免常见的” NullPointerException”

安全调用

与一个可以为空的对象交互式很简单的,”?”只会在这个对象存在的时候调用,否则将会忽略它,安全运行程序.

val context : Context? = null
val res = context?.getResources() // 不会崩溃,但是 res 将为空.

聪明的做法

如果你继续使用可以为空的对象,代码最终会是这样:

val context : Context? = null
val res = context?.getResources()
val appName = res?.getString(R.string.app_name)
val shortName = appName?.substring(0, 2)

这是很可怕的,你可以使用其他更好的方法,只是检测如果 context 不为空,其他的对象将是非空对象:

val context : Context? = null
if (context != null) {
    val res = context.getResources()    // 不需要 '?'
    val appName = res.getString(R.string.app_name)
    val shortName = appName.substring(0, 2)
}
val context : Context? = null
context?.let {
    val res = context.getResources()    // 不需要'?'
    val appName = res.getString(R.string.app_name)
    val shortName = appName.substring(0, 2)
}

Elvis 操作 ?:

使用”?:”操作符你可以为这个对象二选一值.它像一个短的空检查.在下面的例子中”message”可以为空,它的类型是” String?”.在这种情况下对象不为空将使用它的值,否则它将使用另一个值.

try {
    // code...
} catch (e: Throwable) {
    Log.e("TAG", e.message ?: "Error message")
}

静态类型

这将意味着 Kotlin 需要只要你在代码中的一切类型,因为编译器将在编译期间检测.Android Studio 将很好的支持,IDE 将做一个伟大的工作帮助我们知道分配一个值到另一个变量.

通常我们不需要指定一个变量的类型.下面的 toolbar 常量,它的类型将会从上下文中推断出来,这是一个其它关于 Kotlin伟大的特征.

val toolbar = findViewById(R.id.toolbar) as Toolbar

类型推断带来了很大的优势:可靠性(编译器将验证程序的正确性)、可维护性(代码通过它本身解析)、工具支持性能

完全与 Java 交互

这是另一个 Kotlin 伟大的特性,你可以在 Kotlin 中使用 Java 代码,反之亦然.

更新 MainActivity

我添加了一些代码到 MainActivity ,打开一个 在下一章创建的 fragment.

注意我们是如何使用 Fragment Manager 的

fun changeFragment(f: Fragment) {
        val ft = supportFragmentManager.beginTransaction()
        ft.replace(R.id.fl_container, f)
        ft.commit()
    }

这个新的方法 changeFragment 将允许我们在 activity 内部打开一个 fragment.

仓库

文章中所有的代码可以在这个仓库中获得

KedditBySteps

结论

这个部分只讲了一小部分关于 Kotlin 的概念,在之后的部分我们将继续学习更多.