AndroID官方推荐使用协程来处理异步问题。以下是协程的特点:
轻量:单个线程上可运行多个协程。协程支持挂起,不会使正在运行协程的线程阻塞。挂起比阻塞节省内存,且支持多个并行 *** 作。内存泄漏更少:使用结构化并发机制在一个作用域内执行多项 *** 作。内置取消支持:取消 *** 作会自动在运行中的整个协程层次结构内传播。Jetpack集成:许多Jetpack库都包含提供全面协程支持的扩展。某些库还提供自己的协程作用域,可用于结构化并发。示例首先工程中需要引入Kotlin与协程。然后再使用协程发起网络请求。
引入AndroID工程中引入Kotlin,参考 Android项目使用kotlin
有了Kt后,引入协程
dependencIEs { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-androID:1.3.9" // 协程}
启动协程不同于Kotlin工程直接使用GlobalScope,这个示例在viewmodel中使用协程。需要使用viewmodelScope
。
下面的CorVm1继承了viewmodel。
import androIDx.lifecycle.viewmodelimport androIDx.lifecycle.viewmodelScope // 引入import kotlinx.coroutines.dispatchersimport kotlinx.coroutines.launchclass CorVm1 : viewmodel() { companion object { const val TAG = "rfDevCorVm1" } fun cor1() { viewmodelScope.launch { Log.d(TAG,"不指定dispatcher ${Thread.currentThread()}") } }}
在按钮的点击监听器中调用cor1()
方法,可以看到协程是在主线程中的。
不指定dispatcher Thread[main,5,main]
由于此协程通过viewmodelScope
启动,因此在viewmodel的作用域内执行。如果viewmodel因用户离开屏幕而被销毁,则viewmodelScope
会自动取消,且所有运行的协程也会被取消。
launch()
方法可以指定运行的线程。可以传入dispatchers
来指定运行的线程。
先简单看一下kotlinx.coroutines
包里的dispatchers,它有4个属性:
Default
,默认Main
,AndroID中指定的是主线程Unconfined
,不指定线程IO
,指定IO线程都通过点击事件来启动
// CorVm1.ktfun ioCor() { viewmodelScope.launch(dispatchers.IO) { Log.d(TAG,"IO 协程 ${Thread.currentThread()}") }}fun defaultCor() { viewmodelScope.launch(dispatchers.Default) { Log.d(TAG,"Default 协程 ${Thread.currentThread()}") }}fun mainCor() { viewmodelScope.launch(dispatchers.Main) { Log.d(TAG,"Main 协程 ${Thread.currentThread()}") }}fun unconfinedCor() { viewmodelScope.launch(dispatchers.Unconfined) { Log.d(TAG,"Unconfined 协程 ${Thread.currentThread()}") }}
运行log
IO 协程 Thread[Defaultdispatcher-worker-1,main]Main 协程 Thread[main,main]Default 协程 Thread[Defaultdispatcher-worker-1,main]Unconfined 协程 Thread[main,main]
从上面的比较可以看出,如果想利用后台线程,可以考虑dispatchers.IO
。Default
用的也是Defaultdispatcher-worker-1
线程。
主线程中不能进行网络请求,我们把请求放到为IO *** 作预留的线程上执行。一些信息用MutableLiveData发出去。
// CorVm1.ktval info1liveData: mutablelivedata<String> = mutablelivedata()private fun reqGet() { info1liveData.value = "发起请求" viewmodelScope.launch(dispatchers.IO) { val url = URL("https://www.baIDu.com/s?wd=abc") try { val conn = url.openConnection() as httpURLConnection conn.requestMethod = "GET" conn.connectTimeout = 10 * 1000 conn.setRequestProperty("Cache-Control","max-age=0") conn.doOutput = true val code = conn.responseCode if (code == 200) { val baos = ByteArrayOutputStream() val inputStream: inputStream = conn.inputStream val inputS = ByteArray(1024) var len: Int while (inputStream.read(inputS).also { len = it } > -1) { baos.write(inputS,len) } val content = String(baos.toByteArray()) baos.close() inputStream.close() conn.disconnect() info1liveData.postValue(content) Log.d(TAG,"net1: $content") } else { info1liveData.postValue("网络请求出错 $conn") Log.e(TAG,"net1: 网络请求出错 $conn") } } catch (e: Exception) { Log.e(TAG,"reqGet: ",e) } }}
看一下这个网络请求的流程
从主线程调用reqGet()
函数viewmodelScope.launch(dispatchers.IO)
在协程上发出网络请求在协程中进行网络 *** 作。把结果发送出去。参考Android项目使用kotlinMutableLiveDataKotlin协程介绍 总结 以上是内存溢出为你收集整理的Android Kotlin协程入门全部内容,希望文章能够帮你解决Android Kotlin协程入门所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)