Android officials recommend using concurrency to deal with asynchronous problems.
Characteristics of collaborative process:
- Lightweight: multiple coroutines can be run on a single thread. The process supports suspension, which will not block the thread running the process. Suspending saves memory than blocking and supports multiple parallel operations.
- Less memory leaks: use structured concurrency to perform multiple operations within a scope.
- Built in cancellation support: the cancellation operation will be automatically propagated within the whole collaboration hierarchy in operation.
- Jetpack integration: many jetpack libraries contain extensions that provide comprehensive collaboration support. Some libraries also provide their own collaboration scope, which can be used for structured concurrency.
Example
Firstly, Kotlin and coprocess need to be introduced into the project. Then use the process to initiate the network request.
introduce:
Introducing kotlin into Android project, refer to Android project uses kotlin
With Kt, the co process is introduced
dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9" // Synergetic process }
Start process
Unlike the Kotlin project, which uses GlobalScope directly, this example uses a collaboration in the ViewModel. viewModelScope is required.
The following CorVm1 inherits the ViewModel.
import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope // introduce import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch class CorVm1 : ViewModel() { companion object { const val TAG = "rfDevCorVm1" } fun cor1() { viewModelScope.launch { Log.d(TAG, "Not specified dispatcher ${Thread.currentThread()}") } } }
Calling the cor1() method in the button click listener, you can see that the association is in the main thread.
Not specified dispatcher Thread[main,5,main]
Since this collaboration is started through viewModelScope, it is executed within the scope of ViewModel. If the ViewModel is destroyed because the user leaves the screen, the viewModelScope will be automatically cancelled and all running collaborations will be cancelled.
The launch() method can specify the thread to run. You can pass in Dispatchers to specify the thread to run.
Let's take a brief look at Dispatchers in the kotlinx.coroutines package. It has four attributes:
- Default, default
- Main, the main thread is specified in Android
- Unconfined, no thread specified
- IO, specify IO thread
Are started by clicking on events
// CorVm1.kt fun ioCor() { viewModelScope.launch(Dispatchers.IO) { Log.d(TAG, "IO Synergetic process ${Thread.currentThread()}") } } fun defaultCor() { viewModelScope.launch(Dispatchers.Default) { Log.d(TAG, "Default Synergetic process ${Thread.currentThread()}") } } fun mainCor() { viewModelScope.launch(Dispatchers.Main) { Log.d(TAG, "Main Synergetic process ${Thread.currentThread()}") } } fun unconfinedCor() { viewModelScope.launch(Dispatchers.Unconfined) { Log.d(TAG, "Unconfined Synergetic process ${Thread.currentThread()}") } }
Run log
IO Synergetic process Thread[DefaultDispatcher-worker-1,5,main] Main Synergetic process Thread[main,5,main] Default Synergetic process Thread[DefaultDispatcher-worker-1,5,main] Unconfined Synergetic process Thread[main,5,main]
As can be seen from the above comparison, if you want to use background threads, you can consider Dispatchers.IO. Default also uses the DefaultDispatcher-worker-1 thread.
Simulate network request
Network requests cannot be made in the main thread. We put the requests on the thread reserved for IO operations. Some messages are sent with MutableLiveData.
// CorVm1.kt val info1LiveData: MutableLiveData<String> = MutableLiveData() private fun reqGet() { info1LiveData.value = "Initiate request" 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, 0, len) } val content = String(baos.toByteArray()) baos.close() inputStream.close() conn.disconnect() info1LiveData.postValue(content) Log.d(TAG, "net1: $content") } else { info1LiveData.postValue("Network request error $conn") Log.e(TAG, "net1: Network request error $conn") } } catch (e: Exception) { Log.e(TAG, "reqGet: ", e) } } }
Take a look at the flow of this network request
- Call the reqGet() function from the main thread
- viewModelScope.launch(Dispatchers.IO) sends a network request on the collaboration
- Carry out network operation in the cooperation process. Send the results.
kotlin collaborative process related knowledge points
1. Basis of collaborative process
- Your first collaboration program
- Bridging the blocking and non blocking world
- Waiting for a task
- Structured concurrency
- Scope builder
- Extraction function reconstruction
- ......
2. Cancellation and timeout
- Cancel the execution of the collaboration
- Cancellation is collaborative
- Make calculation code cancelable
- Release resources in finally
- Run code blocks that cannot be cancelled
- overtime
3. Access
- Channel foundation
- Close and iterate channels
- Build channel producer
- The Conduit
- Use the prime of the pipe
- Fan out
- Fan in
- Buffered channel
- The channel is fair
- timer channel
4. Combine pending functions
- Default sequential call
- Using async concurrency
- Lazy start async
- async style functions
- Structured concurrency using async
5. Collaboration context and scheduler
- Scheduler and thread
- Unrestricted scheduler vs restricted scheduler
- Debugging procedures and threads
- Jump between different threads
- Tasks in context
- Subprocess
- Responsibilities of parent process
- Name the coroutine for debugging
- Combining elements in context
- Cancel by explicit task
- Thread local data
6. Exception handling
- Abnormal propagation
- CoroutineExceptionHandler
- Cancellation and exception
- Abnormal aggregation
- supervise
7. select expression
- select in channel
- select when the channel is closed
- Select to send
- Select delay value
- Switch on delay value channel
8. Shared variable state and concurrency
- problem
- volatile doesn't help
- Thread safe data structure
- Limit threads at fine granularity
- Restrict threads with coarse granularity
- mutex
- Actors
[Kotlin getting started to proficient in a full range of video references]