10天学会kotlin DAY10 协程 lanch 详解

data class LoginRegisterResponse(

val admin: Boolean,

val chapterTops: List<*>,

val collectIds: List<*>,

val email: String?,

val icon: String?,

val id: String?,

val nickname: String?,

val password: String?,

val publicName: String?,

val token: String?,

val type: Int,

val username: String?

)

定义一个接口 代码如下:WanAndroidAPI

interface WanAndroidAPI {

// TODO 下面是传统方式API

/** https://www.wanandroid.com/blog/show/2

  • 登录API

  • username=Derry-vip&password=123456

*/

@POST(“/user/login”)

@FormUrlEncoded

fun loginAction(

@Field(“username”) username: String,

@Field(“password”) password: String

)
Call<LoginRegisterResponseWrapper> // 返回值

}

接口的实现 代码如下:APIClient

class APIClient {

/**

  • 单例

*/

private object Holder {

val INSTANCE = APIClient()

}

companion object { // 派生

val instance = Holder.INSTANCE

}

fun instanceRetrofit(apiInstance: Class): T {

// OkHttpClient 请求服务器

val mOkHttpClient = OkHttpClient().newBuilder().apply {

readTimeout(10000, TimeUnit.SECONDS) //添加超时时间

connectTimeout(10000, TimeUnit.SECONDS) //添加连接超时时间

writeTimeout(10000, TimeUnit.SECONDS) // 添加写入超时时间

}.build()

val retrofit = Retrofit.Builder()

.baseUrl(“https://www.wanandroid.com”)

// 请求方 ←

.client(mOkHttpClient)

// 响应方 →

// Response的事情 回来

.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // RxJava来处理

.addConverterFactory(GsonConverterFactory.create()) // Gson 来解析 — JavaBean

.build()

return retrofit.create(apiInstance)

}

}

XML 代码如下

<?xml version="1.0" encoding="utf-8"?>

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=“http://schemas.android.com/apk/res/android”

xmlns:app=“http://schemas.android.com/apk/res-auto”

xmlns:tools=“http://schemas.android.com/tools”

android:layout_width=“match_parent”

android:layout_height=“match_parent”

tools:context=“.ui.MainActivity”>

<TextView

android:id=“@+id/textview”

android:text=“启动线程”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

tools:ignore=“MissingConstraints” />

<Button

android:id=“@+id/button”

android:onClick=“startRequest”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:text=“网络请求”

app:layout_constraintBottom_toBottomOf=“parent”

app:layout_constraintLeft_toLeftOf=“parent”

app:layout_constraintRight_toRightOf=“parent”

app:layout_constraintTop_toTopOf=“parent”

tools:ignore=“OnClick” />

</androidx.constraintlayout.widget.ConstraintLayout>

具体功能实现,直接看代码吧,注释比较多

代码如下: MainActivity

class MainActivity : AppCompatActivity() {

private var mProgressDialog: ProgressDialog? = null

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

}

fun startRequest(view: View){

mProgressDialog = ProgressDialog(this)

mProgressDialog?.setTitle(“请求服务器中…”)

mProgressDialog?.show()

// TODO 第一步:异步线程开启,请求服务器

object: Thread(){

override fun run() {

super.run()

Thread.sleep(2000) // 模拟一个两秒的加载时间

val loginResult = APIClient.instance.instanceRetrofit(WanAndroidAPI::class.java)

.loginAction(“Derry-vip”, “123456”)

val result: LoginRegisterResponseWrapper? = loginResult.execute().body()

// 切换到主线程, 更新UI 把最终的javaBean 发送给Handler

val msg = mHandler.obtainMessage()

msg.obj = result

mHandler.sendMessage(msg)

}

}.start()

}

// TODO 第二步:主线程更新UI

val mHandler = Handler(Looper.getMainLooper()){

// as 类型转换

val result = it.obj as LoginRegisterResponseWrapper

textview.text = result.data.toString() // 更新控件 UI

mProgressDialog?.hide()

false

}

}

上面的代码实现,是传统完成的异步加载操作。需要先开启一个异步线程,然后再把登录成功的数据,再交给主线线程去做UI的更新操作。

2.2:协程方式完成异步任务网络加载


再来实现一个协程的

修改 WanAndroidAPI 里面的接口,添加 suspend 关键字,代码如下:

@POST(“/user/login”)

@FormUrlEncoded

suspend fun loginActionCoroutine(

@Field(“username”) username: String,

@Field(“password”) password: String

)
LoginRegisterResponseWrapper // 返回值

修改 MainActivity 中的代码,代码如下:

class MainActivity1 : AppCompatActivity() {

private var mProgressDialog: ProgressDialog? = null

private val main = MainScope()

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

}

fun startRequest(view: View) {

mProgressDialog = ProgressDialog(this)

mProgressDialog?.setTitle(“请求服务器中…”)

mProgressDialog?.show()

// launch 在Android 中使用的时候,它默认的是 IO 线程,所以需要修改成Main 线程 (Dispatchers.Main )

main.launch(Dispatchers.Main) {

// 1.挂起出去执行异步线程 2. 操作完成之后,恢复主线程

val result = APIClient.instance.instanceRetrofit(WanAndroidAPI::class.java)

.loginActionCoroutine(“Derry-vip”, “123456”)

// 更新UI

textview.text = result.data.toString()

mProgressDialog?.hide()

}

}

override fun onDestroy() {

super.onDestroy()

main.cancel()

}

}

是不是简单了很多呢?不再需要创建异步线程,然后再交给主线程去修改UI,而是直接使用 launch 挂起出去执行异步操作,操作完成后直接恢复到主线程

这只是一个简单的一层回调的例子,可以想象一些,如果老板让我们实现一个三层回调,30层回调的时候,我们使用传统的处理方式会有多疼苦,接下来我们来实现一下。

2.3:传统方式完成三层回调


先写个回调接口 代码如下 ResponseCallback

/**

  • 模拟请求服务器后,相应结果信息

*/

interface ResponseCallback {

/**

  • 请求服务器 加载成功

*/

fun responseSuccess(serverResponseInfo: String)

/**

  • 请求服务器 加载失败

*/

fun responseError(serverResponseErrorMsg: String)

}

再写三个模拟数据请求的异步线程 代码如下:

/**

  • 第一层

  • 请求加载 [用户数据]

  • responseCallback [回调给外界的接口]

*/

private fun requestLoadUser(responseCallback: ResponseCallback) {

val isLoadSuccess = true // 加载成功 或 失败的标记

object : Thread() {

override fun run() {

super.run()

try {

sleep(3000L) // 模拟请求 所造成的耗时

if (isLoadSuccess) {

responseCallback.responseSuccess(“加载到[用户数据]信息集”)

} else {

responseCallback.responseSuccess(“加载[用户数据],加载失败,服务器宕机了”)

}

} catch (e: InstantiationException) {

e.printStackTrace()

}

}

}.start()

}

/**

  • 第二层

  • 请求加载 [用户资产数据]

  • responseCallback [回调给外界的接口]

*/

private fun requestLoadUserAssets(responseCallback: ResponseCallback) {

val isLoadSuccess = true // 加载成功 或 失败的标记

object : Thread() {

override fun run() {

super.run()

try {

sleep(3000L)

if (isLoadSuccess) {

responseCallback.responseSuccess(“加载到[用户资产数据]信息集”)

} else {

responseCallback.responseError(“加载[用户资产数据],加载失败,服务器宕机了”)

}

} catch (e: InstantiationException) {

e.printStackTrace()

}

}

}.start()

}

/**

  • 第三层

  • 请求加载 [用户资产详情数据]

  • responseCallback [回调给外界的接口]

*/

private fun requestLoadUserAssetsDetails(responseCallback: ResponseCallback) {

val isLoadSuccess = true // 加载成功 或 失败的标记

object : Thread() {

override fun run() {

super.run()

try {

sleep(3000L)

if (isLoadSuccess) {

responseCallback.responseSuccess(“加载到[用户资产数据]信息集”)

} else {

responseCallback.responseError(“加载[用户资产数据],加载失败,服务器宕机了”)

}

} catch (e: InstantiationException) {

e.printStackTrace()

}

}

}.start()

}

具体功能实现,直接看代码吧,没什么好讲的

代码如下: MainActivity

class MainActivity2 : AppCompatActivity() {

private var mProgressDialog: ProgressDialog? = null

private val main = MainScope()

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

}

fun startRequest(view: View) {

mProgressDialog = ProgressDialog(this)

最后

总之啊,家里没矿的同学们,如果你们想以后的日子过得好一些,多想想你们的业余时间怎么安排吧;

技术方面的提升肯定是重中之重,但是技术外的一些“软实力”也不能完全忽视,很多时候升职确实是因为你的技术足够强,但也与你的“软实力”密切相关

在这我也分享一份大佬自己收录整理的 Android学习PDF+架构视频+面试文档+源码笔记 ,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅并给下属员工学习的精品资料。在脑图中,每个知识点专题都配有相对应的实战项目,可以有效的帮助大家掌握知识点。

总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习

相信自己,没有做不到的,只有想不到的

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

mProgressDialog = ProgressDialog(this)

最后

总之啊,家里没矿的同学们,如果你们想以后的日子过得好一些,多想想你们的业余时间怎么安排吧;

技术方面的提升肯定是重中之重,但是技术外的一些“软实力”也不能完全忽视,很多时候升职确实是因为你的技术足够强,但也与你的“软实力”密切相关

在这我也分享一份大佬自己收录整理的 Android学习PDF+架构视频+面试文档+源码笔记 ,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅并给下属员工学习的精品资料。在脑图中,每个知识点专题都配有相对应的实战项目,可以有效的帮助大家掌握知识点。

总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习

[外链图片转存中…(img-6iIzsolr-1714226896929)]

[外链图片转存中…(img-o96ZNi0w-1714226896930)]

相信自己,没有做不到的,只有想不到的

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 9
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kotlin协程是一种轻量级的线程处理机制,它可以在不创建新线程的情况下实现异步操作。Kotlin协程的优势在于它提供了一种结构化并发的方式,使得异步代码更加易于编写和维护。下面是深入理解Kotlin协程的一些方法和步骤: 1. 协程的基本概念:协程是一种轻量级的线程处理机制,它可以在不创建新线程的情况下实现异步操作。协程的本质是一种协作式的多任务处理机制,它可以在同一个线程中切换执行不同的任务,从而实现异步操作。 2. 协程的使用方法:在Kotlin中,协程的使用方法非常简单。首先需要导入kotlinx.coroutines库,然后使用launch函数创建一个协程。在协程中可以使用挂起函数来实现异步操作,例如delay函数可以让协程暂停一段时间。 3. 协程的挂起函数:协程的挂起函数是一种特殊的函数,它可以让协程暂停执行,等待某个条件满足后再继续执行。在Kotlin中,常用的挂起函数包括delay函数、withContext函数和async函数等。 4. 协程的上下文:协程的上下文是一种特殊的对象,它包含了协程的执行环境和状态信息。在Kotlin中,协程的上下文可以通过CoroutineContext对象来表示,它包含了协程的调度器、异常处理器和其他一些属性。 5. 协程的异常处理:协程的异常处理是一种特殊的机制,它可以让协程在发生异常时自动恢复或者终止执行。在Kotlin中,协程的异常处理可以通过try-catch语句或者CoroutineExceptionHandler对象来实现。 6. 协程的取消:协程的取消是一种特殊的机制,它可以让协程在不需要继续执行时自动终止。在Kotlin中,协程的取消可以通过cancel函数或者协程作用域来实现。 下面是一个使用Kotlin协程实现异步操作的例子: ```kotlin import kotlinx.coroutines.* fun main() = runBlocking { val job = launch { delay(1000L) println("World!") } println("Hello,") job.join() } ``` 输出结果为: ``` Hello, World! ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值