本文目录:

  • 一、Kotlin特性
  • 1、变量
  • 2、常量
  • 3、类型推断:
  • 4、null类型限制:
  • 5、分支(条件语句)
  • 5.1 分支1:if-else
  • 5.2 分支2:when、else、-> 的搭配
  • 6、函数:
  • 6.1 声明定义:
  • 6.2 特性简化:
  • 6.3 匿名函数:
  • 6.4 高阶函数:参数有函数的
  • 7、类(属性+函数)
  • 属性默认权限:public
  • 构造函数的构建:
  • 类的实例化(使用构造函数)、类对象的属性的调用:
  • 类函数:
  • 二、Kotlin在安卓开发中常见的代码总结:
  • 1、使用 Fragment
  • 2、推迟变量的初始化:late-init
  • 3、事件的匿名函数:
  • 4、伴生对象:companion object
  • 5、属性委托:by
  • 6、null的注意:
  • 6.1 在Java中书写习惯:方便与kotlin协同
  • 6.2 处理kotlin中的null值:
  • 7、变量初始化:
  • 7.1 在类声明的时候直接初始化:
  • 7.2 在init块中初始化
  • 7.3 先null,后面尽快初始化
  • 7.4 lateinit延迟初始化:比上一个好



参考:Android官网:https://developer.android.google.cn

一、Kotlin特性

1、变量

var count: Int = 10

  • var:变量
  • count:变量名
  • Int:整型,类似的还有:Byte、Short、Long、Float 和 Double
  • 注意声明的时候,如果不使用类型推断,则变量名和变量类型使用英文冒号连为一体。使用的时候,只需要使用变量名即可。句尾不需要写分号。
    如: count=20

2、常量

val languageName: String = “Kotlin”

varr改成l即可,但是不可再次赋值,因为是常量。

3、类型推断:

val languageName = “Kotlin”

val upperCaseName = languageName.toUpperCase()

显然languageName是字符串String类型
声明变量 的时候,可以 只赋值,而省略掉 变量的类型
此时,系统会根据 赋值的字面值 来推断该变量的数据类型,从而节省代码量。

4、null类型限制:

//错误示范:
val languageName: String = null

  • 注意:以上代码错误
  • 原因:Kotlin语言对变量的null类型进行了限制,默认情况下,变量不能为null类型,也就是变量必须要有对应变量类型的值。
  • 废话:这种方式虽然让Kotlin语言难了一点,但是保证了代码的安全(因为如果变量的值为null,并且被程序使用,可能会让应用无故崩溃闪退,这是谁也不愿意看到的)

//正确示范:类型后面加个问号即可
val languageName: String? = null

上面的String?表示:变量可以拥有两种类型:
1、String类型:可以把字符串赋值给它
2、null类型:可以把null赋值给它

5、分支(条件语句)

5.1 分支1:if-else

if (count == 42) {
    println("I have the answer.")
} else {
    println("The answer eludes me.")
}
if (count == 42) {
    println("I have the answer.")
} else if (count > 35) {
    println("The answer is close.")
} else {
    println("The answer eludes me.")
}

//上面的代码可以简写成:
val answerString: String = if (count == 42) {
    "I have the answer."
} else if (count > 35) {
    "The answer is close."
} else {
    "The answer eludes me."
}
println(answerString)

//上面代码的说明:
if-else语句中最后一个字面值,都可以表示为该分支(最终只有一条为真)的返回值。

上面的语句的意思就是使用一个变量来接受if-else分支结构的返回值。
在一定程度上减少了println的代码

5.2 分支2:when、else、-> 的搭配

when{}
条件-> 语句
else->语句

val answerString = when {
    count == 42 -> "I have the answer."
    count > 35 -> "The answer is close."
    else -> "The answer eludes me."
}

println(answerString)

6、函数:

6.1 声明定义:

// fun 函数名():返回类型,没有时可不写
fun generateAnswerString(): String {
    val answerString = if (count == 42) {
        "I have the answer."
    } else {
        "The answer eludes me"
    }
    return answerString
}

//带参函数:
fun generateAnswerString(countThreshold: Int): String {
    val answerString = if (count > countThreshold) {
        "I have the answer."
    } else {
        "The answer eludes me."
    }
    return answerString
}

6.2 特性简化:

//利用if-else返回值的特性简化代码:
fun generateAnswerString(countThreshold: Int): String {
    return if (count > countThreshold) {
        "I have the answer."
    } else {
        "The answer eludes me."
    }
}

//再次简化代码(简单函数,可省略return,用赋值符号替代):
fun generateAnswerString(countThreshold: Int): String = if (count > countThreshold) {
        "I have the answer"
    } else {
        "The answer eludes me"
    }

6.3 匿名函数:

val stringLengthFunc: (String) -> Int = { input ->
    input.length
}

//说明(难度系数5星):
1、常量val,变量名为stringLengthFunc,这个变量用来干嘛呢?看它冒号后面的
	数据类型,(String) -> Int,这个可能最难理解。
	(参数类型)->函数返回值类型
	1、首先,小括号我们可以理解成函数,因为函数的函数名后面常常都携带一个小括号。
	至于这里为什么没有函数名?因为这是匿名函数呀,自然要省略函数名。
	2、其次,箭头和后面的Int又是什么意思呢?我们都知道,函数有两个非常重要的组成部分
	一个是函数名,另一个是函数返回类型。因为是匿名函数,所以函数名没了,
	而函数返回类型却不能省略,所以,Int这里就是它的函数返回类型。
2、后面的赋值符号=又是什么意思:
	这就是前面说的,省略return,使用赋值符号取而代之的骚操作,
	没有return的时候就不会这样写了,所以他就是return的简写版而已。
3、最后面的:input ->
    input.length
    其实这就像lambda表达式一样,input是实参,箭头后面才是函数体。

注意:如果匿名函数没有返回值(自然也就没有return),那就会相当于全部省略,
只保留大括号,让人难以看出。今后要是遇到匿名函数,要心里留个底
避免傻傻看不出。

6.4 高阶函数:参数有函数的

fun stringMapper(str: String, mapper: (String) -> Int): Int {
    // Invoke function
    return mapper(str)
}
//大家一定要习惯匿名函数的:(参数类型)->函数返回值类型 这种类型组合。
//还要习惯类型后置的这种写法。最初看起来很别扭,但真的有用。
mapper:函数引用(你可以理解成一个函数指针)
//高阶函数调用:
stringMapper("Android", { input ->
    input.length
})

//如果函数参数在最后一个:参数可以写在外部————
stringMapper("Android") { input ->
    input.length
}

7、类(属性+函数)

属性默认权限:public

class Car {
    val wheels = listOf<Wheel>()
}

构造函数的构建:

class Car(val wheels: List<Wheel>){...}

//注意:
构造函数可以直接在声明类的类名后面当作函数一样传入函数参数

类的实例化(使用构造函数)、类对象的属性的调用:

val car = Car() // construct a Car
val wheels = car.wheels // retrieve the wheels value from the Car

类函数:

class Car(val wheels: List<Wheel>) {//构造函数参数可以直接写在这
    private val doorLock: DoorLock = ...//变量属性
    fun unlockDoor(key: Key): Boolean {//类内函数
        // Return true if key is valid for door lock, false otherwise
    }
}

二、Kotlin在安卓开发中常见的代码总结:

1、使用 Fragment

class LoginFragment : Fragment()//继承

override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
): View? {
    return inflater.inflate(R.layout.login_fragment, container, false)
}
//上诉代码说明:override:表示后面的函数是重写父类Fragment的已有的函数。

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
}
//上诉代码说明:super表示父类的一个实例,如果需要调用父类的函数(代码),就需要用super

2、推迟变量的初始化:late-init

class LoginFragment : Fragment() {
//变量定义的时候可以先不初始化,但尽量尽快初始化
    private lateinit var usernameEditText: EditText
    private lateinit var passwordEditText: EditText
    private lateinit var loginButton: Button
    private lateinit var statusTextView: TextView

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

        usernameEditText = view.findViewById(R.id.username_edit_text)
        passwordEditText = view.findViewById(R.id.password_edit_text)
        loginButton = view.findViewById(R.id.login_button)
        statusTextView = view.findViewById(R.id.status_text_view)
    }

    ...
}

3、事件的匿名函数:

//button的点击事件,因为没有返回值,所以匿名函数几乎全部省略,其实这里是使用匿名函数。
//如果是Java,可能会这样写:loginButton.setOnClickListener( a,{...});
//但是Kotlin没有返回值的匿名函数几乎全部隐匿,甚至函数调用的小括号都省略了。
loginButton.setOnClickListener {
    val authSuccessful: Boolean = viewModel.authenticate(
            usernameEditText.text.toString(),
            passwordEditText.text.toString()
    )
    if (authSuccessful) {
        // Navigate to next screen
    } else {
        statusTextView.text = requireContext().getString(R.string.auth_failed)
    }
}

4、伴生对象:companion object

class LoginFragment : Fragment() {

    ...

    companion object {//相当于Java的static变量,仅存一份实例,伴随该类
        private const val TAG = "LoginFragment"
    }
}

5、属性委托:by

注意:属性委托使用反射,这样会增加一些性能开销。这种代价换来的是简洁的语法,可让您节省开发时间。

//在初始化变量(对象)的时候,常常需要其他父类的支持:
private val viewModel: LoginViewModel by viewModels()

6、null的注意:

6.1 在Java中书写习惯:方便与kotlin协同

public class Account implements Parcelable {
    public final String name;
    public final String type;
    private final @Nullable String accessId;//可以为null
    ...
}
public class Account implements Parcelable {
    public final @NonNull String name;//不可为null
    ...
}

6.2 处理kotlin中的null值:

1、变量后面带 !! 运算符:

断定name为非null,强制执行,但如果为null就会报异常。所以这种写法其实回到了Java的模式上了。

val account = Account("name", "type")
val accountName = account.name!!.trim()

2、更安全的写法:?.+?:

val account = Account("name", "type")
val accountName = account.name?.trim()

//为了避免null值向下传递()虽然使用?.以后该语句不会报异常,但是结果仍会为null
//建议使用下面的写法。如果是null,就用最后的值赋值给最左边的变量accountName(失败后的退路)
val accountName = account.name?.trim() ?: "Default name"

骚操作:

fun validateAccount(account: Account?) {
    val accountName = account?.name?.trim() ?: "Default name"

    // account变量在此处之外不能为null。
    //提前返回
    account ?: return
    ...
}

7、变量初始化:

7.1 在类声明的时候直接初始化:

class LoginFragment : Fragment() {
    val index: Int = 12//初始化变量
}

7.2 在init块中初始化

class LoginFragment : Fragment() {
    val index: Int

    init {//在块中初始化
        index = 12
    }
}

7.3 先null,后面尽快初始化

class LoginFragment : Fragment() {
    private var statusTextView: TextView? = null//先可null

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

            statusTextView = view.findViewById(R.id.status_text_view)//初始化
            statusTextView?.setText(R.string.auth_failed)
    }
}

7.4 lateinit延迟初始化:比上一个好

class LoginFragment : Fragment() {
    private lateinit var statusTextView: TextView//延迟初始化

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

            statusTextView = view.findViewById(R.id.status_text_view)//初始化
            statusTextView.setText(R.string.auth_failed)
    }
}