Android kotlin 专题

Android kotlin 专题

零蚀
[🔗 kotlin 官方文档]
[🔗 协程 github]
[🔗 Kotlin 从入门到出门] (这里会有比较详细的kotlin内容)


kotlin 基础

  • 空安全设计

    通过IDE的提示来避免对null对象的创建。所以kotlin里面的变量默认不被设置为空。强硬的报错会提示你参数不能设计为null,但是还是会有其应用场景,比如findViewById,所以设置了lateinit的关键字的选项lateinit 用来阻止IDE的初始化检查和报错

    lateinit var text:TextView
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    
        text=findViewById(R.id.text_temporary)
    }
    

    当然kotlin事支持用id来直接代替控件的(在老版中需要手动来添加一些依赖),直接省去了findViewById的繁琐,但可读性你懂的。

    text_temporary.text="设置了一文本"
    

    或者使用?解除非空对象,且在属性对象后加?也是解除非空限制,且线程安全。

    var view:View?
    name?.length
    
  • 基本类型
    var number: Int = 1 
    var c: Char = 'c'
    var b: Boolean = true
    var array: IntArray = intArrayOf(1, 2) 
    

    Int类型是否装箱是根据情况而定,不是像java的Integer一定就是装箱。

  • 类和对象

    在kotlin中默认的是public,而构造方法可以如下构建:

    class A_Demo{
        constructor()
    
        constructor(a:Int)
    
        constructor(a:Int,b:String)
    }
    

    当然设置主构造方法时也可以这么写(但是使用了主构造函数,其他构造函数必须调用这个构造函数,主构造函数的参数可供类属性和init{}调用,而init中的数据处理就是主构造方法中的处理,其次这里的参数可以不写var,写了表示它默认生成了一行var a=a,供以下代码调用):

    class A_Demo constructor(var a:Int){
        // 其他构造方法的写法
        constructor(str:String,name: Int) :this(name){
        
        }
    }
    
    // 简洁化
    class A_Demo constructor(var a:Int,var str:String =""){}
    
    // 简洁化终版
    class A_Demo(var a:Int,var str:String =""){}
    

    kotlin 中用了constructor来区别其中的fun。还有当我门创建类,没有命名时候,其实类默认为"final"所以不可被调用,需要转为open才可被调用

    open class B_Demo{}
    

    java中的代码块和kotlin中的代码块写法也是不同的,我们都知道java的代码块执行是在构造方法之后,他们写法也如下

    // java
    {
        Log.e(xx,xx)
    }
    // kotlin
    init{
        Log.e(xx,xx)
    }
    
  • 其他常见关键字
    kotlin常见的关键字Java中对应的关键字
    isinstanceof
    as强转
  • object
    • object 单例

    object不是一个类,是一个修饰词,专门修饰类,并直接生成一个对象,而使用这个类的对象直接使用类名,这也就成了单例。而被object修饰的属性&方法,也全部定义为静态的属性&方法。(实现的单例是一个饿汉式的单例,并且实现了线程安全)

    fun test() {
        Single_Demo.a
        Single_Demo.b
    }
    
    object Single_Demo{
        val a:String="八岐大蛇"
        var b={
            print("萨斯ki")
            print("无良商家")
        }
    }
    
    • object 实现接口(类似于实现java匿名内部类)
    // text_temporary.setOnClickListener { TODO("not implemented") }
    
    val listener=object:View.OnClickListener{
            override fun onClick(v: View?) {
                TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
            }
    
        }
        text_temporary.setOnClickListener(listener)
    
    
  • object静态方法和静态属性
    class Static_demo{
        var a=""
        object static_param{
            var b=0
        
            fun c(){
                print("python scrapy")
            }
        }
    }
    // 调用
    Static_demo.static_param.b
    Static_demo.static_param.c()
    

    当然kotlin官方给了更为简洁的写法,有效的缓解了命名尴尬症,而伴生对象的实际作用也就是:省事。

    class Static_demo{
        var a=""
        companion object {
            var b=0
    
            fun c(){
                print("python scrapy")
            }
        }
    }
    // 调用
    Static_demo.b
    Static_demo.c()
    

    当然官方还提出了更省事的写法,类似于python模块编程,kotlin的包內编程方式,它和静态方法静态变量一样都是全局的。kotlin称其为 顶层申明

    var b=0
    fun c(){
        print("python scrapy")
    }
    class Staticdemo{
        var a=""
    }
    // 调用
    b
    c()
    
  • 数组和集合
    • 数组
    val strs: Array<String> = arrayOf("a", "b", "c")
    

    数组增加了很多功能:

    var array= intArrayOf(1,2,3,5,6)
    var newArray=array.map { it+1 } //每个item+1
    var newArray=array.filter { it%2==0 } // 每个item条件过滤
    var newArray=array.map { listOf("${it+1}","快乐风男","NO$it") }// 将每个item构成集合再将数据扁平化进一个数组中
        ……
    
    • 集合
    var list_name = listOf("a","b") // var list:List<String>
    var set_name= setOf("a","b") // var set:Set<String>
    var map_name= mapOf("a" to "aa","b" to "bb") //var map:Map<String,String>
    

    而这些数组并没有set功能,只能get到value,如果想用set方法的话,用调用以下数组。

    var list_name = mutableListOf("a","b") 
    var set_name= mutableSetOf("a","b") 
    var map_name= mutableMapOf("a" to "aa","b" to "bb")
     
    

泛型

  • 泛型解释

    java 的泛型不支持协变(字类的泛型可以赋值给父类),保障类型安全,但是kotlin支持,使用“?”是可以解除这一问题,但是这样有局限性,

    • extends:当你用了如下?extends E,时,你是不可调用其中包含E的方法的,从原则上来讲就是不可以对E有具体的改动,除了null,它们的作用主要可以扩大接受范围,例如fun(List<? extends TextView>)—> list.add(Button) button时text的子View。
    • super:super 恰好相反,限制和extends相反,他不能获取包含E的返回值,不能获得包含含有类型的字段值,list.add(View)
    List<? extends TextView> list1
    List<? super TextView> list2
    List<?> list3
    

    对应在kotlin中的泛型:

    • out:只输出不输入,只读不写,
    • in:只输入不输出,只写不读,
    var list1:List<out TextView> 
    var list2: ArrayList<in TextView> // List源码指定了out
    var list3:List<*> //out any
    

    java 里面设置上界,上界若有多个可以使用“&”作为连接,

    class TestDemo<T extends View & List>  // 上界
    
    

    kotlin设置上界

    //上界
    // class TestDemo<T:View> //单个写法
    class TestDemo<T> where T : View, T : List<*> {}//多个写法
    

    reified:在Java 中功能泛型不可以instance和对象进行匹配的,但是kotlin中可以使用reified解除限时,

    inline fun <reified T> printIfTypeMatch(item: Any) {
        if (item is T) { // 没有inline和reified 这里就不会在提示错误了
            println(item)
        }
    }
    

协程

  • 协程介绍

    [🔗 协程 github]

    让我想起了Python协程,python 里的协程相较于线程优于网络连接,劣于文件I/O(一些文档上一家之言),本质协程是一种轻量级的线程(这个是错误的,官方比较对象有误,kotlin的协程对比的应该是线程池不是单个线程),kotlin里的协程的使用概念是针对任意的耗时操作。
    kotlin协程launch也对线程API进行了封装这样可以起到并发操作。协程就是一个线程框架,它在kotlin中最大的优点就是方便。

    ⚠️非阻塞式挂起-解析

    • 挂起:所谓的kotlin挂起是指一个事务(对一件事的处理方式,此处是对线程&协程运行时候,协程脱离线程,运行完毕后,协程回到线程的这件事儿)。

    • 非阻塞式:所谓的不卡线程,java的切换线程也是非阻塞式,java的非阻塞式讲的是单线程会耗时操作卡线程,kotlin的单协程(他会切换线程🙄🙄,其实就是java里的切线程)不会卡线程。其实该阻塞的都阻塞了(因为网络速度/ IO速度必然低于CPU运算),对比的参考系不一样,就如同:一个人做两件事和两个人做两件事,肯定前者必然阻塞,后者有条不紊的进行,这不能说明前者的人种不如后者人种,thread和协程亦如此。

    thread
    coroutines
    切回/不切回(可选)
    协程&线程
    偶遇suspend(挂起)函数
    协程和线程分离
    线程:奔向自由
    协程:在suspend指定线程里work

    由上图可见kotlin协程的定义,是对协程切回的这中处理方式为非阻塞式挂起

    // 伪代码
    ...
    suspend fun suspendwork(){
        // 指定suspends和线程分手后切换的线程,如果没有指定,就不切了。
        // withContext中含有挂起函数代码
        withContext(Dispathcher.IO){
            ....
        }
    }
    launch{
        suspendwork()
    }
    

    「suspend」的作用是在于:提醒,提醒这是个后台耗时的函数,是开发者对使用者的提醒,挂起操作是其内部的实际代码(比喻delay)。

  • 协程使用
    buildscript {
        ...
        ext.kotlin_coroutines = '1.3.1' // 一般已经定义好了
        ...
    }
        dependencies {
        ...
        //  依赖协程核心库
        implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines"
        //  依赖当前平台所对应的平台库
        implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines"
        ...
    }
    

    切换前后台

    fun CoroutineScope.foo() {
        // 将任务切到后台
        launch(Dispatchers.IO) {
    
        }
        // 将任务切到前台
        launch (Dispatchers.Main){
    
        }
    }
    
    //其它方式
    coroutineScope.launch(Dispatchers.Main) {      // 在 UI 线程开始
        val image = withContext(Dispatchers.IO) {  // 切换到 IO 线程,并在执行完成后切回 UI 线程(withContext是一个 suspend 函数,它需要在协程或者是另一个 suspend 函数中调用。)
            getImage(imageId)                      
        }
        avatarIv.setImageBitmap(image)             //  回到 UI 线程更新 UI
    } 
    

    合并多个网络请求数据

    fun CoroutineScope.foo() {
            launch (Dispatchers.Main){
                val a=async { api.getData(user) }
                val b=async { api.get(user) }
                val merge = suspendingMerge(a,b)
            }       
        }
        
     suspend fun suspendingMerge(vararg params: Deferred<Any>,errorBlock:suspend CoroutineScope.(Exception) -> Unit): MutableList<Any> {
        val list = mutableListOf<Any>()
        try {
            list.addAll(mutableListOf(params.map { it.await() }))
        }catch (e:Exception){
            errorBlock(e)
        }
        return list
    }
    
    

    launch 创建一个协程并指定一个线程去执行,suspend挂起函数,在函数fun之前申明,此函数为挂起函数,


🔗 前言
🔗 Android 专题列表
🔗 Android Git专题
🔗 Android 项目架构 专题
🔗 Android 组件化&插件化 专题
🔗 Android Gradle 专题
🔗 Android 热更新 专题
🔗 Annotation Processing 专题
🔗 Android RecyclerView 专题
🔗 Android JavaIO NIO OKIO 专题
🔗 Android 全埋点 专题列表

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

零蚀zero eclipse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值