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中对应的关键字 is instanceof 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) } }
协程
-
协程介绍
让我想起了Python协程,python 里的协程相较于线程优于网络连接,劣于文件I/O(一些文档上一家之言),本质协程是一种轻量级的线程(这个是错误的,官方比较对象有误,kotlin的协程对比的应该是线程池不是单个线程),kotlin里的协程的使用概念是针对任意的耗时操作。
kotlin协程launch也对线程API进行了封装这样可以起到并发操作。协程就是一个线程框架,它在kotlin中最大的优点就是方便。⚠️非阻塞式挂起-解析
-
挂起:所谓的kotlin挂起是指一个事务(对一件事的处理方式,此处是对线程&协程运行时候,协程脱离线程,运行完毕后,协程回到线程的这件事儿)。
-
非阻塞式:所谓的不卡线程,java的切换线程也是非阻塞式,java的非阻塞式讲的是单线程会耗时操作卡线程,kotlin的单协程(他会切换线程🙄🙄,其实就是java里的切线程)不会卡线程。其实该阻塞的都阻塞了(因为网络速度/ IO速度必然低于CPU运算),对比的参考系不一样,就如同:一个人做两件事和两个人做两件事,肯定前者必然阻塞,后者有条不紊的进行,这不能说明前者的人种不如后者人种,thread和协程亦如此。
由上图可见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 全埋点 专题列表