10天学会kotlin DAY10 协程 lanch 详解

        .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<LoginRegisterResponse>? = 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<LoginRegisterResponse>

    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<LoginRegisterResponse>  // 返回值



> 修改 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)

    mProgressDialog?.setTitle("请求服务器中...")

    mProgressDialog?.show()

// TODO 先执行 异步请求 1

    requestLoadUser(object : ResponseCallback {

        override fun responseSuccess(serverResponseInfo: String) {

// 从异步 切换到主线程,更新UI

            val handler = object : Handler(Looper.getMainLooper()) {

                override fun handleMessage(msg: Message) {

                    super.handleMessage(msg)



                    textview.text = serverResponseInfo

                    textview.setTextColor(Color.GRAY)

// TODO 先执行 异步请求 2

                    requestLoadUserAssets(object : ResponseCallback {

                        override fun responseSuccess(serverResponseInfo: String) {

                            val handler = object : Handler(Looper.getMainLooper()) {

                                override fun handleMessage(msg: Message) {

                                    super.handleMessage(msg)



                                    textview.text = serverResponseInfo

                                    textview.setTextColor(Color.RED)



                                    //                      TODO 先执行 异步请求 3



                                    requestLoadUserAssetsDetails(object : ResponseCallback {

                                        override fun responseSuccess(serverResponseInfo: String) {

                                            val handler =

                                                object : Handler(Looper.getMainLooper()) {

                                                    override fun handleMessage(msg: Message) {

                                                        super.handleMessage(msg)



                                                        textview.text = serverResponseInfo

                                                        textview.setTextColor(Color.BLUE)

                                                        mProgressDialog?.hide()



                                                    }

                                                }



                                            handler.sendEmptyMessage(0)

                                        }



                                        override fun responseError(serverResponseErrorMsg: String) {

// TODO 失败的的逻辑就不写了

                                        }



                                    })

                                }

                            }

                            handler.sendEmptyMessage(0)

                        }



                        override fun responseError(serverResponseErrorMsg: String) {

// TODO 失败的的逻辑就不写了

                        }



                    })

                }

            }

            handler.sendEmptyMessage(0)

        }



        override fun responseError(serverResponseErrorMsg: String) {

// TODO 失败的的逻辑就不写了

        }



    })



}

}




无限嵌套,让我想起了flutter 中的嵌套陷阱。  

再看一下 使用**协程** 实现的三层回调



[]( )2.4:协程方式解决三层回调带

-----------------------------------------------------------------------------



> 先定义三个方法,分别开启一个异步线程。 代码如下:



/**

  • 请求加载[用户数据]

  • suspend 就是一个提醒的作用,提醒用户,当前函数是挂起的函数,可能执行异常操作

*/

private suspend fun requestLoadUser(): String{

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

// 此协程能够保证在异步执行

withContext(Dispatchers.IO){

    delay(3000)     //模拟请求服务器,造成的耗时

}

if (isLoadSuccess){

    return "加载到[用户数据]信息集"

}else{

    return "加载[用户数据],加载失败,服务器宕机了"

}

}

/**

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

*/

private suspend fun requestLoadUserAssets(): String{

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

// 此协程能够保证在异步执行

withContext(Dispatchers.IO){

    delay(3000)     //模拟请求服务器,造成的耗时

}

if (isLoadSuccess){

    return "加载到[用户资产数据]信息集"

}else{

    return "加载[用户资产数据],加载失败,服务器宕机了"

}

}

/**

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

*/

private suspend fun requestLoadUserAssetsDetails(): String{

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

// 此协程能够保证在异步执行

withContext(Dispatchers.IO){

    delay(3000)     //模拟请求服务器,造成的耗时

}

if (isLoadSuccess){

    return "加载到[用户资产详情数据]信息集"

}else{

    return "加载[用户资产详情数据],加载失败,服务器宕机了"

}

}




> 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()

// Dispatchers.Main 包裹一层 Handler 切换主线程

    GlobalScope.launch(Dispatchers.Main) {

// TODO 先执行 异步请求1

        var serverResponseInfo = requestLoadUser()

        textview.text = serverResponseInfo    // 更新UI

        textview.setTextColor(Color.YELLOW)   // 更新UI

// TODO 更新UI完成后 异步请求2

        serverResponseInfo = requestLoadUserAssets()

        textview.text = serverResponseInfo    // 更新UI

        textview.setTextColor(Color.RED)   // 更新UI

// TODO 更新UI完成后 异步请求3

        serverResponseInfo = requestLoadUserAssetsDetails()

        textview.text = serverResponseInfo    // 更新UI

        textview.setTextColor(Color.BLUE)   // 更新UI



        mProgressDialog?.hide()

    }



}

}




看到这里,是不是发现很简单呢?



* * *



[]( )总结

================================================================



难道协程很 ”高效“,”轻量“我们就要用协程吗?  

答:其实协程的真正魅力是,`最大程度简化异步并发任务,用同步代码写出异步效果`



> 🤩  

> 🎉 原 创 不 易 , 还 希 望 各 位 大 佬 支 持 一 下 \\textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下  

>   

> 👍 点 赞 , 你 的 认 可 是 我 创 作 的 动 力 ! \\textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!  

>   

> 🌟 收 藏 , 你 的 青 睐 是 我 努 力 的 方 向 ! \\textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!  

>   

> ✏️ 评 论 , 你 的 意 见 是 我 进 步 的 财 富 ! \\textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值