Kotlin

2022-09-20  本文已影响0人  放羊娃华振

一、为什么要优先使用 Kotlin 进行 Android 开发?

我们查看了直接来自与会开发者、我们的客户顾问委员会 (CAB)、Google Developers 专家 (GDE) 的反馈,以及我们通过开发者调研获得的反馈。许多开发者已喜欢上使用 Kotlin,且提供更多 Kotlin 支持的呼声很高。下面介绍了开发者喜欢用 Kotlin 编写代码的原因:

二、Kotlin常用知识

1.变量声明

Kotlin 使用两个不同的关键字(即 val [不可修改] 和 var[可修改])来声明变量:

    //可变变量赋值
    var str: String = "str1"

    //变量可赋空值
    var str2: String? = null

    //延迟赋值使用lateinit
    lateinit var str3: String

    //val类似java的final关键字
    val str4: String = "final str"

    //下面是自动类型推断的写法
    var str5 = "str5"
    var int6 = 5
2.数据类型
    val arr1 = arrayOf("a", "b", "c")
    for (i in arr1.indices) {
        println("地${i}个元素是${arr1[i]}")
    }
    arr1.set(2, "f")

    for ((index, value) in arr1.withIndex()) {
        println("地${index}个元素是${value}")
    }
 //不能调用add方法
    var set1 = setOf<String>("1", "2", "3")
    //取值
    var v1: String = set1.elementAtOrElse<String>(0, defaultValue = { "0" })

    //可以调用add方法
    var mutaset2 = mutableSetOf<String>("1", "2", "3")
    mutaset2.add("4")
    //取值
    var v2: String? = mutaset2.elementAtOrElse<String>(1, { "0" })
    var v3: String? = mutaset2.elementAtOrElse<String>(1) { "0" }

    val size = set1.size
    println("set size:${size}")

    //遍历方式1
    for (item in mutaset2) {
        print(item)
        print(" ")
    }
    println()

    //遍历方式二
    val iterator = mutaset2.iterator()
    while (iterator.hasNext()) {
        print(iterator.next())
        print(" ")
    }
    println()

    //遍历方式三
    mutaset2.forEach {
        print(it)
        print(" ")
    }
    println()

MutableSet常用方法,更多方法可以点击MutableSet 方法

属性 描述
fun add(element: E): Boolean 将给定元素添加到集合中
fun addAll(elements: Collection< E>): Boolean 将给定集合的所有元素添加到当前集合中
fun clear() 将删除此集合中的所有元素
fun iterator(): MutableIterator< E> 它返回此对象元素的迭代器
fun remove(element: E): Boolean 如果指定元素存在于集合中,将从此集合中删除单个指定元素
fun removeAll(elements: Collection< E>): Boolean 会删除集合中指定的当前集合中的所有元素
fun retainAll(elements: Collection< E>): Boolean 仅保留当前集合中存在于指定集合中的那些元素
fun contains(element: E): Boolean 检查当前集合中是否包含的指定元素
fun containsAll(elements: Collection< E>): Boolean 检查当前集合中是否存在指定集合的所有元素
fun isEmpty(): Boolean 如果集合为空(不包含任何元素),则返回true,否则返回false
fun Iterable.any(): Boolean 如果集合包含至少一个元素,则返回true
fun Iterable.any(predicate: (T) -> Boolean): Boolean 如果至少元素与给定的谓词匹配,则返回true
fun Iterable.distinct(): List 返回一个列表,其中只包含给定集合中的不同元素
fun Iterable.drop(n: Int): List 返回一个列表,其中包含除前n个元素之外的所有元素
fun Iterable.elementAt(index: Int): T 返回给定索引处的元素,或者如果集合中不存在给定索引则抛出IndexOutOfBoundException
fun Iterable.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T 如果索引在当前集合中超出范围,它将返回给定索引处的元素或调用defaultValue函数的结果
fun <T : Comparable> Iterable.max(): T? 返回最大的元素,如果集合中没有元素,则返回null
fun <T : Comparable> Iterable.min(): T? 返回最小的元素,如果集合中没有元素,则返回null
fun MutableCollection.remove(element: T): Boolean 如果它存在于当前集合中,它将删除单个指定元素
fun MutableCollection.removeAll(elements: Collection): Boolean 删除了包含在指定集合中的当前集合的所有元素。
fun MutableCollection.retainAll(elements: Collection): Boolean 保留当前集合中包含在指定集合中的所有元素
fun Iterable.reversed(): List 以相反的顺序返回元素
 // list不能调用add方法,不能修改
    var list1 = listOf<Int>(1, 2, 3, 4)
    var v5 = list1.get(0)
    var v6 = list1[0]

    var list2 = mutableListOf<Int>(1, 2, 3, 4)
    //设置元素
    list2.set(1, 5)
    list2[1] = 5
    //添加元素
    list2.add(7)
    var v7 = list2[0]
    println("list size:${list2.size}")

    //遍历方式1
    list2.forEach {
        print(it)
        print(" ")
    }
    println()

    //遍历方式2
    val iterator = list2.iterator()
    while (iterator.hasNext()){
        print(iterator.next())
        print(" ")
    }
    println()

    //遍历方式三
    for(item  in list2){
      print("${item} ")
    }
    println()

//遍历方式四 获取index
    fun forTest() {
        val list = mutableListOf(1, 2, 3, 4, 5)
        for (index in 0 until list.size) {
            println("index=${index}")
        }
//遍历方式五 获取index
fun forTest() {
        val list = mutableListOf(1, 2, 3, 4, 5)
        for (index in 0 .. list.size) {
            println("index=${index}")
        }
    }
//遍历方式六 获取index
    fun forTest() {
        val list = mutableListOf(1, 2, 3, 4, 5)
        for ((index, value) in list.withIndex()) {
            println("index=${index}")
            println("value=${value}")
        }
    }

    val map1 = mapOf("key1" to 1, "key2" to 2)
    val entries = map1.entries
    for (item in entries) {
        println("key为${item.key}的值是${item.value}")
    }
    println()

    val map2 = mutableMapOf<String, Int>("key1" to 1, "key2" to 2)
    map2.put("ke3",3)
    for((k,v) in map2){
        println("key为${k}的值是${v}")
    }
    println()

    map2.remove("key2")
    val iterator = map2.iterator()
    while(iterator.hasNext()){
        val next = iterator.next()
        println("key为${next.key}的值是${next.value}")
    }
3.Kotlin 条件语句

    //这块主要看看基础语法:https://kotlinlang.org/docs/basic-syntax.html
    //    比较测试一
    var name = ""
    if (name.equals("")) {
        println("name is null")
    }

    //    比较测试二
    val x = 10
    val y = 9
    if (x in 1..y + 1) {
        println("fits in range")
    }

    //    比较测试三
    val list = listOf("a", "b", "c")

    if (-1 !in 0..list.lastIndex) {
        println("-1 is out of range")
    }
    if (list.size !in list.indices) {
        println("list size is out of valid list indices range, too")
    }

    //    kotln中使用when代理switch,参考:https://kotlinlang.org/docs/basic-syntax.html#when-expression
    var key = 3
    when (key) {
        1 -> println("打印了1")
        2 -> println("打印了2")
        3 -> println("打印了3")
    }

4.Kotlin的表达式

语句没有值,总是包围着它代码块中的顶层元素,表达式有值,能作为另一个表达式的一部分。举个例子:
java代码:

public int max(int a, int b) {
    if (a > b) {
        return a;
    } else {
        return b;
    }
}

Kotlin代码:(Kotlin中,if是表达式,不是语句,可以直接return if表达式)

fun max(a: Int, b: Int): Int {
    return if (a > b) a else b
}

其余常用的表达式可以参考:
https://www.jianshu.com/p/2a1755457add/

5.Kotlin String模板

主要是怎么输出String的各种数据格式:

val i = 10
println("i = $i") // Prints "i = 10"
val s = "abc"
println("$s.length is ${s.length}") // Prints "abc.length is 3"

更多细节可以参考:https://kotlinlang.org/docs/strings.html#string-templates

6.Kotlin函数
fun double(a: Int): Int {
    return a * 2
}
//没有返回值,Unit可以不写,等同于fun printMethod(txt: String)
fun printMethod(txt: String): Unit {
    println(txt)
}
fun method1(x: Int, useCache: Boolean = false, str: String = "defaultStr") {
    println("x:${x}")
    println("useCache:${useCache}")
    println("str:${str}")
}
//调用的时候可以使用method1(10), 其余参数都是使用默认值
method1(10)
//调用的时候使用 method1(x = 20),就是指定给哪个参数赋值
 method1(x = 20)
open class A {
    open fun method(i: Int = 10) { /*……*/ }
}

class B : A() {
    override fun method(i: Int) { /*……*/ }  // 不能有默认值
}
fun getList(vararg strs: String):List<String>{

    var list =ArrayList<String>()
    for(item in strs) {
        list.add(item)
    }
    return list;

}

泛型实现方式:

//这里的T代表泛型,总是泛型总是出现在函数名的前面
fun <T> asList(vararg ts: T): List<T> {
    val result = ArrayList<T>()
    for (t in ts) // ts is an Array
        result.add(t)
    return result
}
//调用的时候,使用逗号分隔
val list = asList(1,2,3)
//当我们已经有一个数组类型的参数的时候,我们可以用扩展符(*)来作为参数传入
val arr = arrayof(1,2,3)
val list = asList(4,5,*arr)
interface Source<out T> {
    fun nextT(): T
}

fun demo(strs: Source<String>) {
    val objects: Source<Any> = strs // 这个没问题,因为 T 是一个 out-参数
    // ……
}

interface Comparable<in T> {
    operator fun compareTo(other: T): Int
}

fun demo(x: Comparable<Number>) {
    x.compareTo(1.0) // 1.0 拥有类型 Double,它是 Number 的子类型
    // 因此,我们可以将 x 赋给类型为 Comparable <Double> 的变量
    val y: Comparable<Double> = x // OK!
}
7.Kotlin类型转换
  var str:String ="123"
    println(  str is String )
    println(  str !is String )

    val value = str as CharSequence
    println(value)
8.kotlin 注解
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION,
        AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.VALUE_PARAMETER,
        AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
annotation class TestAnnotationTarget
//声明无参注解
annotation class AnnotationTest

//使用有参注解
@AnnotationTest
fun testMethod() {
    println()
}

//声明有参注解
annotation class AnnotationTest1(val str: String)

//使用有参注解
@AnnotationTest1(str = "aaa")
fun testMethod1() {
    println()
}
9.kotlin协程
//测试协程的使用
    private fun runCoroutines() {

        GlobalScope.launch(Dispatchers.Main) {
            val data = getNetData()
            val processData = procesData(data)
            Log.i(TAG, processData)
        }
    }

    //处理网络请求返回的数据
    private suspend fun procesData(data: String?): String? {
        val dd = data
        return withContext(Dispatchers.IO) {
            Log.i(TAG, "数据是:${dd}")
            Log.i(TAG, "开始处理数据了")
            delay(1000)
            Log.i(TAG, "成功处理数据了")
            dd?.split("-")
                    ?.map { it.capitalize() }
                    ?.reduce { acc, s -> acc + s }

        }
    }

    //模拟网络请求获取数据
    private suspend fun getNetData(): String {

        return withContext(Dispatchers.IO) {
            Log.i(TAG, "开始获取数据了")
            delay(2000)
            Log.i(TAG, "成功获取数据了")
            "hello-abc"
        }

    }

几个开启协程Scope的区别

  1. CoroutineScope
    他会跟踪所有协程。同样他还可以取消由它所启动的所有协程。
  2. GlobalScope
    声明周期是process级别的。即使Activty与Fragment已经被销毁,协程仍然在运行。
  3. MainScope
    通常在 在Activity中使用。 在onDestory 要记得手动销毁掉。
  4. viewModelScope
    只能在ViewModel中使用。绑定viewModel的生命周期
  5. lifecycleScope
    只能在Activity、Fragment中使用。并且会和Activity、Fragment生命周期进行绑定。
    参考一个在Activity中使用的例子:https://blog.csdn.net/mp624183768/article/details/125139784
10.kotlin之let、with、run、apply、also
方法 上下文对象 返回值 扩展函数 使用场景
let it lambda 结果 在非空对象上执行一个 lambda或者在局部域中引入一个变量
with this lambda 结果 在一个对象上组合函数调用
run this lambda 结果 对象配置并计算结果
apply this 上下文对象 对象配置
also it 上下文对象 额外的效果
非扩展函数run lambda 结果 在需要表达式的地方运行语句

表格里的上下文对象中,this 是可以省略的, it 是隐含的默认参数名,可以显式地指定为其他名字。

   var str: String? = "hello world"

    //let 链式调用中最后一行是返回值会带到下个调用中。
    str?.let { it ->
        println("第一次收到let值:${it}")
        "第一次处理let${it}"
    }.let {
        println("第二次收到let值:${it}")
    }

    println("let 处理后:${str}")

    println("-------------------------------")

    //with  最后一行是返回值有作用
    // https://www.jianshu.com/p/272372acc00c
    //写法一
    var withStr: String = with(str, {
        println("收到with的值:${this}")
        "返回with的值:${this}"
    })
    println("==withStr 处理后==>${withStr}")

    with(str) {
        println("长度是:${this?.length}")
    }

    println("with 处理后:${str}")

    println("-------------------------------")

    //run 最后一行是返回值有作用
    str.run {
        println("收到run的值:${this}")
        "run1"
    }.run {
        println("收到run的值:${this}")
    }

    var runStr: String = str.run {
        "run  -------------${this}"
    }
    println("run 处理后:${runStr}")

    println("-------------------------------")

    //apply 最后一行是返回值没作用
    str.apply {
        println("收到apply的值1:${this}")
        "11111"
    }.apply {
        println("收到apply的值2:${this}")
        "2222"
    }.apply {
        println("收到apply的值3:${this}")
    }

    var applyStr: String? = str.apply {
        println("收到apply的值:${this}")
//        "apply-${this}"
    }
    println("apply 处理后:${applyStr}")

    println("-------------------------------")
    //also 最后一行是返回值没作用
    str.also {
        println("收到also的值1:${it}")
//        "ddddd"
    }.also {
        println("收到also的值2:${it}")
    }
//打印日志
/**
第一次收到let值:hello world
第二次收到let值:第一次处理lethello world
let 处理后:hello world
-------------------------------
收到with的值:hello world
==withStr 处理后==>返回with的值:hello world
长度是:11
with 处理后:hello world
-------------------------------
收到run的值:hello world
收到run的值:run1
run 处理后:run  -------------hello world
-------------------------------
收到apply的值1:hello world
收到apply的值2:hello world
收到apply的值3:hello world
收到apply的值:hello world
apply 处理后:hello world
-------------------------------
收到also的值1:hello world
收到also的值2:hello world
*/

有篇文章写的不错可以看看:https://www.jianshu.com/p/ba89322cf92d

11.kotlin之takeIf、takeUnless
    println("-------------------------------")
    //takeIf 当代码块的返回false,对象为空链式调用终止
    var name:String="放羊娃"
    name.takeIf {
        it.length>4
    }?.let {
        println("测试takeif:${it}")
    }

    println("-------------------------------")
    //takeUnless 当代码块的返回true,对象为空链式调用终止
    name.takeUnless {
        it.length>4
    }.let {
        println("测试takeUnless:${it}")
    }

三、常用的写法

Activity示例:

class KotlinTestActivity : AppCompatActivity() , View.OnClickListener {
    override fun onClick(v: View?) {
    }
}

单例示例:

class SingleDemo {
    companion object {
        val instance: SingleDemo by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) { SingleDemo() }
    }

    fun doTask(){
        println("调用到我了")
    }
}

fun main() {
    SingleDemo.instance.doTask()
}

在推荐其余的单例写法:https://www.jianshu.com/p/2497f6a5a461

Kotlin工具类Util的示例:

//需要构建MyAppUtil对象的方式
open class MyAppUtil {
    fun getImei(): String? {
        return "imei"
    }
}
//调用
var util=  MyAppUtil()
util.getImei()

//类似java的static的形式
object MyAppUtil2{
    fun getAnroidId():String?{
        return "android id"
    }
}
//调用
MyAppUtil2.getAnroidId()

Kotlin利用Gson解析json

//数据实体
data class Entity(
     val nickname: String,
    @SerializedName("xname") 
    var name: String
)

//调用解析方法
val json = Gson().fromJson(result, Entity::class.java)

Kotlin构造函数可以参考

//@JvmOverloads 加了这个注解就相当生成了一个、两个、三个参数的构造函数了
class CustomTextView @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : AppCompatTextView(context, attrs, defStyleAttr) {

    init {
        //设置ui啥的
    }
}

//不用@JvmOverloads 可以自己添加一个和两个的构造方法
class CustomTextView constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : AppCompatTextView(context, attrs, defStyleAttr) {

    constructor(context: Context) : this(context, null, 0) {
        //todo something
    }

    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) {
        //todo something
    }

    init {
        //todo something
    }

}

//Kotlin方法返回对象

data class User(val name: String?, val age: Int) {

}

fun getUser(name: String?, age: Int): User {
    return User(name, age)
}

fun main() {
    val user = getUser("阿美", 19)
    print(user.toString())
}

Kotlin解构解构参考

data class User(val name: String?, val age: Int) {

}

fun getUser(name: String?, age: Int): User {
    return User(name, age)
}

fun main() {
    val user = getUser("阿美", 19)
    print(user.toString())

    var (a,b)=user
    print("${a},${b}")
}

Kotlin闭包的写法:


fun main() {

    var result= test("22", ::getWord2)
    println("final result==>${result}")
}

fun getWord2(name: String, age: Int): String {
    println("getword2 收到参数: ${name} -${age}")
    return "getword2 返回的参数 ${name} -${age}";
}

fun test(name: String, getWord: (String, Int) -> String) {
    println("test String ==>${name}")
    var age = 100
    println("test getword:")
    println(getWord(name, age))
}

//打印结果
/**
test String ==>22
test getword:
getword2 收到参数: 22 -100
getword2 返回的参数 22 -100
final result==>kotlin.Unit
*/

kotlin匿名函数

fun main() {

    println(blessFunction())
    println(blessFunction2())
    println(blessFunction3())
    println(blessFunction4("hhhhhh"))

}

var blessFunction: () -> String = {

    "bless function return value"
}

var blessFunction2: () -> Unit = {

    println("blessFunction2")
}

var blessFunction3 = {

    "blessFunction3"
}

var blessFunction4: (str: String) -> String = {
    "bless function return value-${it}"
}
//打印结果
/**
bless function return value
blessFunction2
kotlin.Unit
blessFunction3
bless function return value-hhhhhh
Function0<java.lang.String>
*/

Kotlin空合并操作符号

    var str:String?=null
    var name: String =str ?:"ddd-----------"
    println(name)

Kotlin先决条件函数


image.png

四、实用代码

1.获取sdkROM大小
//ROM内存大小,返回 64G/128G/256G/512G
    private fun getTotalRom(): String {
        val dataDir = Environment.getDataDirectory();
        val stat = StatFs(dataDir.path)
        val blockSize:Long = stat.blockSizeLong
        val totalBlocks:Long = stat.blockCountLong
        val size:Long = totalBlocks * blockSize
        val GB:Long = 1024 * 1024 * 1024
        val deviceRomMemoryMap = arrayOf(
            2 * GB,
            4 * GB,
            8 * GB,
            16 * GB,
            32 * GB,
            64 * GB,
            128 * GB,
            256 * GB,
            512 * GB,
            1024 * GB,
            2048 * GB
        )
        val displayRomSize = arrayOf(
            "2GB",
            "4GB",
            "8GB",
            "16GB",
            "32GB",
            "64GB",
            "128GB",
            "256GB",
            "512GB",
            "1024GB",
            "2048GB"
        )

        var resultJ = 0
        for (i in deviceRomMemoryMap.indices) {
            resultJ = i
            if (size <= deviceRomMemoryMap[i]) {
                break
            }
            if (i == deviceRomMemoryMap.size) {
                resultJ = i - 1
            }
        }
        return displayRomSize[resultJ]
    }

五、参考文档

https://developer.android.google.cn/kotlin/learn
https://kotlinlang.org/docs/basic-syntax.html

上一篇下一篇

猜你喜欢

热点阅读