当前位置:网站首页>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
🤩
️
边栏推荐
- What should I do if I fail to apply for the mime database? The experience from failure to success is shared with you ~
- 敏捷之道 | 敏捷开发真的过时了么?
- Who is the fish and who is the bait? Summary of honeypot recognition methods from the perspective of red team
- Parti,谷歌的自回归文生图模型
- kotlin 初始化块
- 3. Caller 服务调用 - dapr
- System status identifier 'hum' for SAP QM inspection lot
- I have fundamentally solved the problem of wechat occupying mobile memory
- [data mining] final review (sample questions + a few knowledge points)
- Sphere, openai and ai21 jointly publish the best practice guidelines for deployment models
猜你喜欢

CVPR 2022 | interprétation de certains documents de l'équipe technique de meituan

1. Snake game design

数据科学家面临的七大挑战及解决方法

华为AppLinking中统一链接的创建和使用

DTU上报的数据值无法通过腾讯云规则引擎填入腾讯云数据库中

How stupid of me to hire a bunch of programmers who can only "Google"!

脚本之美│VBS 入门交互实战

工业物联网(IIoT)的八个主要趋势

Nifi from introduction to practice (nanny level tutorial) - environment

Getting started with the lvgl Library - colors and images
随机推荐
Teach you how to use airtestide to connect your mobile phone wirelessly!
工业物联网(IIoT)的八个主要趋势
Perhaps the greatest romance of programmers is to commemorate their dead mother with a software
Sphere, openai and ai21 jointly publish the best practice guidelines for deployment models
Definition and use of constants in C language
物联网?快来看 Arduino 上云啦
Main steps of system test
CVPR 2022 | 美團技術團隊精選論文解讀
Nifi from introduction to practice (nanny level tutorial) - environment
Richard Sutton, the father of reinforcement learning, paper: pursuing a general model for intelligent decision makers
Understanding openstack network
C语言中常量的定义和使用
华为AppLinking中统一链接的创建和使用
39 - read XML node and attribute values
Getting started with the go Cobra command line tool
金鱼哥RHCA回忆录:DO447管理项目和开展作业--为ansible剧本创建一个项目
Android kotlin 大全
#yyds干货盘点# 解决剑指offer:调整数组顺序使奇数位于偶数前面(二)
MySQL interview questions
The 35 "top 100 counties" of tmall 618 agricultural products come from the central and western regions and Northeast China