当前位置:网站首页>Detailed explanation of kotlin collaboration lanch

Detailed explanation of kotlin collaboration lanch

2022-06-24 13:35:00 Hua Weiyun

@[TOC](kotlin coroutines lanch Detailed explanation )


Preface

Use pure code Add The way of annotating , You can understand the source code faster
If you like , Please give me a compliment , In the later stage, we will continue to explain in depth


One 、 What is the schedule ?

1. Most developers compare collaborative processes to : Thread encapsulation framework , From a macro perspective , This makes sense
2. A coroutine is a bit like a lightweight thread
3. From the perspective of inclusion relationship , The relationship between coroutine and thread , It's kind of like “ The relationship between thread and process ”, After all , A coroutine cannot run out of a thread
4. Although a coroutine cannot run without a thread , But you can switch between different threads

Two 、 The traditional way to complete asynchronous network loading and collaborative process comparison

2.1: Traditional way to complete asynchronous task network loading

Next, simulate login through an interface , To realize the traditional step-by-step task network loading login scenario

The code is as follows :LoginRegisterResponseWrapper

data class LoginRegisterResponseWrapper<T>(val data: T, val errorCode: Int, val errorMsg: String)

The code is as follows :LoginRegisterResponse

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

Define an interface The code is as follows :WanAndroidAPI

interface WanAndroidAPI {// TODO  Here's the traditional way API    /** https://www.wanandroid.com/blog/show/2 *  Sign in API * username=Derry-vip&password=123456 */    @POST("/user/login")    @FormUrlEncoded    fun loginAction(        @Field("username") username: String,        @Field("password") password: String    )            : Call<LoginRegisterResponseWrapper<LoginRegisterResponse>>   //  Return value }

Interface implementation The code is as follows :APIClient

class APIClient {    /** *  Single case  */    private object Holder {        val INSTANCE = APIClient()    }    companion object {    //  The derived         val instance = Holder.INSTANCE    }    fun <T> instanceRetrofit(apiInstance: Class<T>): T {// OkHttpClient  Request server         val mOkHttpClient = OkHttpClient().newBuilder().apply {            readTimeout(10000, TimeUnit.SECONDS)     // Add timeout             connectTimeout(10000, TimeUnit.SECONDS)   // Add connection timeout             writeTimeout(10000, TimeUnit.SECONDS)    //  Add write timeout         }.build()        val retrofit = Retrofit.Builder()            .baseUrl("https://www.wanandroid.com")            //  Requesting party  ←            .client(mOkHttpClient)            //  Responder  →            // Response Things about   Come back             .addCallAdapterFactory(RxJava2CallAdapterFactory.create())     // RxJava To deal with it             .addConverterFactory(GsonConverterFactory.create())            // Gson  Parsing  --- JavaBean            .build()        return retrofit.create(apiInstance)    }}

XML The code is as follows

<?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=" Start thread "        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=" Network request "        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>

Specific function realization , Just look at the code , There are a lot of comments
The code is as follows : 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(" Request server ...")        mProgressDialog?.show()// TODO  First step : Asynchronous thread on , Request server         object: Thread(){            override fun run() {                super.run()                Thread.sleep(2000)   //  Simulate a two second loading time                 val loginResult = APIClient.instance.instanceRetrofit(WanAndroidAPI::class.java)                    .loginAction("Derry-vip", "123456")                val result: LoginRegisterResponseWrapper<LoginRegisterResponse>? = loginResult.execute().body()//  Switch to the main thread ,  to update UI  Put the final javaBean  Send to Handler                val msg = mHandler.obtainMessage()                msg.obj = result                mHandler.sendMessage(msg)            }        }.start()    }    // TODO  The second step : The main thread updates UI    val mHandler = Handler(Looper.getMainLooper()){// as  Type conversion         val result = it.obj as LoginRegisterResponseWrapper<LoginRegisterResponse>        textview.text = result.data.toString()   //  Update controls  UI        mProgressDialog?.hide()        false    }}

The code above implements , It is a traditional asynchronous loading operation . You need to start an asynchronous thread first , Then put the data of successful login , Then give it to the main thread to do UI Update operation for .

2.2: The asynchronous task network loading is completed in the way of collaborative process

And then realize a collaborative process

modify WanAndroidAPI The interface inside , add to suspend keyword , The code is as follows :

    @POST("/user/login")    @FormUrlEncoded    suspend fun loginActionCoroutine(        @Field("username") username: String,        @Field("password") password: String    )            : LoginRegisterResponseWrapper<LoginRegisterResponse>  //  Return value 

modify MainActivity The code in , The code is as follows :

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(" Request server ...")        mProgressDialog?.show()// launch  stay Android  When used in , The default is  IO  Threads , So it needs to be changed to Main  Threads  (Dispatchers.Main )        main.launch(Dispatchers.Main) {            // 1. Hang out to execute asynchronous threads  2.  After the operation , Restore the main thread             val result = APIClient.instance.instanceRetrofit(WanAndroidAPI::class.java)                .loginActionCoroutine("Derry-vip", "123456")//  to update UI            textview.text = result.data.toString()            mProgressDialog?.hide()        }    }    override fun onDestroy() {        super.onDestroy()        main.cancel()    }}

Is it much simpler ? There is no need to create asynchronous threads , Then give it to the main thread to modify UI, But directly launch Hang out to perform asynchronous operations , After the operation is completed, directly restore to the main thread

This is just a simple example of a layer 1 callback , Imagine some , If the boss asks us to implement a three-tier callback ,30 Layer callback , How painful it will be for us to use the traditional treatment , Now let's do it .

2.3: The traditional way is to complete the three-tier callback

Write a callback interface first The code is as follows ResponseCallback

/** *  After impersonating the request server , Corresponding result information  */interface ResponseCallback {    /** *  Request server   Loading successful  */    fun responseSuccess(serverResponseInfo: String)    /** *  Request server   Loading failed  */    fun responseError(serverResponseErrorMsg: String)}

Write three more asynchronous threads that simulate data requests The code is as follows :

/** *  first floor  *  Request load  [ User data ] * * responseCallback [ Callback to the external interface ] */private fun requestLoadUser(responseCallback: ResponseCallback) {    val isLoadSuccess = true        //  Loading successful   or   Failed flag     object : Thread() {        override fun run() {            super.run()            try {                sleep(3000L)     //  Simulation of the request   The resulting time-consuming                 if (isLoadSuccess) {                    responseCallback.responseSuccess(" Load into [ User data ] Information set ")                } else {                    responseCallback.responseSuccess(" load [ User data ], Loading failed , Server down ")                }            } catch (e: InstantiationException) {                e.printStackTrace()            }        }    }.start()}/** *  The second floor  *  Request load  [ User asset data ] * * responseCallback [ Callback to the external interface ] */private fun requestLoadUserAssets(responseCallback: ResponseCallback) {    val isLoadSuccess = true        //  Loading successful   or   Failed flag     object : Thread() {        override fun run() {            super.run()            try {                sleep(3000L)                if (isLoadSuccess) {                    responseCallback.responseSuccess(" Load into [ User asset data ] Information set ")                } else {                    responseCallback.responseError(" load [ User asset data ], Loading failed , Server down ")                }            } catch (e: InstantiationException) {                e.printStackTrace()            }        }    }.start()}/** *  The third level  *  Request load  [ User asset details data ] * * responseCallback [ Callback to the external interface ] */private fun requestLoadUserAssetsDetails(responseCallback: ResponseCallback) {    val isLoadSuccess = true        //  Loading successful   or   Failed flag     object : Thread() {        override fun run() {            super.run()            try {                sleep(3000L)                if (isLoadSuccess) {                    responseCallback.responseSuccess(" Load into [ User asset data ] Information set ")                } else {                    responseCallback.responseError(" load [ User asset data ], Loading failed , Server down ")                }            } catch (e: InstantiationException) {                e.printStackTrace()            }        }    }.start()}

Specific function realization , Just look at the code , Nothing to say
The code is as follows : 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(" Request server ...")        mProgressDialog?.show()// TODO  Execute first   Asynchronous requests  1        requestLoadUser(object : ResponseCallback {            override fun responseSuccess(serverResponseInfo: String) {//  From asynchronous   Switch to the main thread , to update UI                val handler = object : Handler(Looper.getMainLooper()) {                    override fun handleMessage(msg: Message) {                        super.handleMessage(msg)                        textview.text = serverResponseInfo                        textview.setTextColor(Color.GRAY)// TODO  Execute first   Asynchronous requests  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  Execute first   Asynchronous requests  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  The logic of failure is not written                                             }                                        })                                    }                                }                                handler.sendEmptyMessage(0)                            }                            override fun responseError(serverResponseErrorMsg: String) {// TODO  The logic of failure is not written                             }                        })                    }                }                handler.sendEmptyMessage(0)            }            override fun responseError(serverResponseErrorMsg: String) {// TODO  The logic of failure is not written             }        })    }}

Unlimited Nesting , It reminds me flutter Nested traps in .
Look again. Use coroutines Implementation of three-tier callback

2.4: Solve the three-layer callback band by means of collaborative process

First define three methods , Start an asynchronous thread respectively . The code is as follows :

/** *  Request load [ User data ] * * suspend  It's a reminder , Remind users , The current function is a pending function , May perform abnormal operations  */private suspend fun requestLoadUser(): String{    val isLoadSuccess = true //  Loading successful , and , Loading failed , The tag //  This coroutine can ensure asynchronous execution     withContext(Dispatchers.IO){        delay(3000)     // Impersonate request server , The resulting time-consuming     }    if (isLoadSuccess){        return " Load into [ User data ] Information set "    }else{        return " load [ User data ], Loading failed , Server down "    }}/** *  Request load [ User asset data ] */private suspend fun requestLoadUserAssets(): String{    val isLoadSuccess = true //  Loading successful , and , Loading failed , The tag //  This coroutine can ensure asynchronous execution     withContext(Dispatchers.IO){        delay(3000)     // Impersonate request server , The resulting time-consuming     }    if (isLoadSuccess){        return " Load into [ User asset data ] Information set "    }else{        return " load [ User asset data ], Loading failed , Server down "    }}/** *  Request load [ User asset details data ] */private suspend fun requestLoadUserAssetsDetails(): String{    val isLoadSuccess = true //  Loading successful , and , Loading failed , The tag //  This coroutine can ensure asynchronous execution     withContext(Dispatchers.IO){        delay(3000)     // Impersonate request server , The resulting time-consuming     }    if (isLoadSuccess){        return " Load into [ User asset details data ] Information set "    }else{        return " load [ User asset details data ], Loading failed , Server down "    }}

MainActivity The specific implementation of the code is as follows :

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(" Request server ...")        mProgressDialog?.show()// Dispatchers.Main  Wrap a layer  Handler  Switch main thread         GlobalScope.launch(Dispatchers.Main) {// TODO  Execute first   Asynchronous requests 1            var serverResponseInfo = requestLoadUser()            textview.text = serverResponseInfo    //  to update UI            textview.setTextColor(Color.YELLOW)   //  to update UI// TODO  to update UI After completion   Asynchronous requests 2            serverResponseInfo = requestLoadUserAssets()            textview.text = serverResponseInfo    //  to update UI            textview.setTextColor(Color.RED)   //  to update UI// TODO  to update UI After completion   Asynchronous requests 3            serverResponseInfo = requestLoadUserAssetsDetails()            textview.text = serverResponseInfo    //  to update UI            textview.setTextColor(Color.BLUE)   //  to update UI            mProgressDialog?.hide()        }    }}

See here , Is it easy to find ?


summary

Isn't the process easy ” Efficient “,” Light weight “ Are we going to use a collaborative process ?
answer : In fact, the real charm of Xiecheng is , Minimize asynchronous concurrent tasks , Write asynchronous effects in synchronous code

🤩
Originality is not easy. , I also hope you guys can support \textcolor{blue}{ Originality is not easy. , I also hope you guys can support }

give the thumbs-up , Your recognition is the driving force of my creation ! \textcolor{green}{ give the thumbs-up , Your recognition is the driving force of my creation !}

Collection , Your favor is the direction of my efforts ! \textcolor{green}{ Collection , Your favor is the direction of my efforts !}

Comment on , Your opinion is the wealth of my progress ! \textcolor{green}{ Comment on , Your opinion is the wealth of my progress !}

原网站

版权声明
本文为[Hua Weiyun]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/175/202206241234579619.html