์๋ ํ์ธ์ ๐
์ค๋์ ์ฝ๋ฃจํด์ ํ์ฉํ์ฌ
์๋๋ก์ด๋์์ ๋ก๋ฉ ํ๋ฉด(๋ค์ด์ผ๋ก๊ทธ)์ ๋ง๋๋ ๋ฐฉ๋ฒ์
ํฌ์คํ ํด๋ณด๋ ค ํฉ๋๋ค.

์ฝ๋ฃจํด์ ๊ธฐ๋ณธ์ ์ธ ์ค๋ช ๊ณผ ์ฌ์ฉ๋ฒ์ ๋ํด์๋
์๋ ํฌ์คํ ๋ค์ ์์ธํ๊ฒ ์ค๋ช ๋์ด ์์ผ๋ ํ์ธ ๋ถํ๋๋ฆฝ๋๋ค ๐
[Kotlin] ์ฝํ๋ฆฐ Coroutine(์ฝ๋ฃจํด)์ ๋ํ์ฌ (1) - CoroutineScope์ CoroutineContext ๋ฐ ๊ธฐ๋ณธ ์ฌ์ฉ๋ฐฉ๋ฒ
์๋ ํ์ธ์ ์ค๋์ ์ฝํ๋ฆฐ์ Coroutine์ ๋ํ์ฌ ํฌ์คํ ํด๋ณด๋ ค ํฉ๋๋ค. Coroutine์ด๋? ํ๋ก๊ทธ๋๋ฐ์์ ํ๋์ ์์ ๋จ์๋ฅผ Routine์ด๋ผ ํ๋๋ฐ ๊ฐ Routine์ด ํ์ (Co)ํ์ฌ ์์ ์ ์ฒ๋ฆฌํ๋ ๊ณผ์ ์ ํฉ์น๊ฒ
devyo-111commit.tistory.com
[Kotlin] ์ฝํ๋ฆฐ Coroutine(์ฝ๋ฃจํด)์ ๋ํ์ฌ (2) - ์ฝ๋ฃจํด Channel(์ฑ๋)
์๋ ํ์ธ์ ์ค๋์ ์ ๋ฒ ํฌ์คํ ์ ์ด์ด์ ์ฝ๋ฃจํด Channel์ ๋ํด ๊ณต๋ถํ ๋ด์ฉ์ ์ ๋ฆฌํด๋ณด๋ ค ํฉ๋๋ค. ์ฝ๋ฃจํด์ ๊ธฐ๋ณธ ์ฌ์ฉ๋ฐฉ๋ฒ์ ์ด์ ํฌ์คํ ์์ ํ์ธํ ์ ์์ผ๋ ํจ๊ป ํ์ธํด๋ณด์ธ์ :) [Kotlin] ์ฝ
devyo-111commit.tistory.com
[Kotlin] ์ฝํ๋ฆฐ Coroutine์ ๋ํ์ฌ (3) - Coroutine Flow(ํ๋ก์ฐ)
์๋ ํ์ธ์๐ ์ค๋์ ์ฝ๋ฃจํด ๊ด๋ จ ๋ง์ง๋ง ํฌ์คํ ์ผ๋ก ์ฝ๋ฃจํด Flow์ ๋ํด ๊ณต๋ถํ ๋ด์ฉ์ ํฌ์คํ ํด๋ณด๋ ค ํฉ๋๋ค. 1. Coroutine Flow๋? Flow๋ ์์ฐจ์ ์ผ๋ก ๊ฐ์ ๋ด๋ณด๋ด๊ณ ์ ์์ ์ผ๋ก ๋๋ ์์ธ๋ก ์๋ฃ๋
devyo-111commit.tistory.com
๋ก๋ฉ ํ๋ฉด์ ๊ตฌ์ฑํ๋๋ฐ ์ฌ๋ฌ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ง๋ง
์ ๊ฐ ์ฑํํ ๋ฐฉ๋ฒ์ Coroutine Flow๋ฅผ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ด์์ต๋๋ค.
1. ๋จผ์ ๊ฐ๋จํ๊ฒ Progress์์ ํ๋ฉด์ ํ์ํ ๋ค์ด์ผ๋ก๊ทธ๋ฅผ ํ๋ ๋ง๋ค์ด์ค๋๋ค.
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/dialogText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="๋ก๋ฉ์ค์
๋๋ค.."
android:textSize="30sp"
android:gravity="center"
/>
<ProgressBar
android:id="@+id/progressBar"
android:layout_below="@+id/dialogText"
style="@android:style/Widget.ProgressBar.Inverse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
import android.app.Dialog
import android.os.Bundle
import com.coroutine.basic.databinding.DialogProgressBinding
class ProgressDialog(owner : MainActivity) : Dialog(owner) {
private lateinit var binding : DialogProgressBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DialogProgressBinding.inflate(layoutInflater).also {
setContentView(it.root)
}
}
}
2. ๋ค์์ ํ์ํ ํ๋ฉด์ ๊ฐ๋จํ๊ฒ ๊ตฌ์ฑํด์ค๋๋ค.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/startBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="64dp"
android:text="์์"
android:textSize="25sp" />
<TextView
android:id="@+id/displayTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/startBtn"
android:layout_centerHorizontal="true"
android:layout_marginTop="32dp"
android:textColor="#FF8A80"
android:textSize="25sp"
android:textStyle="bold" />
</RelativeLayout>
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.coroutine.basic.databinding.ActivityMainBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
private lateinit var binding : ActivityMainBinding
private lateinit var startFlow : kotlinx.coroutines.flow.Flow<Int>
private lateinit var mProgressDialog: ProgressDialog
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater).also {
setContentView(it.root)
}
mProgressDialog = ProgressDialog(this) // Dialog ์์ฑ
addListeners()
}
private fun addListeners() {
with(binding){
startBtn.setOnClickListener {
if(::mProgressDialog.isInitialized){ // Dialog๊ฐ ์ด๊ธฐํ ๋์๋ ํ์
mProgressDialog.show()
}
CoroutineScope(Dispatchers.Default).launch{
onClickStart()
}
CoroutineScope(Dispatchers.Main).launch {
startFlow.collect{
//Flow์์ ์ ๋ฌ ๋ฐ์ ๊ฐ์ main Dispatcher์์ TextView์ ์
๋ฐ์ดํธ
binding.displayTV.text = "Progressing ${it*10}%"
}
}
}
}
}
private suspend fun onClickStart() { // ์์ ๋ฒํผ์ด ๋๋ ธ์๋ progress์ฆ๊ฐ
var value = 0
startFlow = flow {
while (value < 10){ //10์ด ๋๋ฉด loop ๋น ์ ธ๋์ค๊ธฐ
delay(1000)
value++
emit(value) //Flow์ ๊ฐ์ emit
}
CoroutineScope(Dispatchers.Main).launch {
//loop(๊ธฐ๋ค๋ ค์ผํ ๋์)๊ฐ ๋๋๋ฉด Dialog ๋ซ๊ธฐ
mProgressDialog.dismiss()
}
}
}
}
์ฝ๋๋ ์์ ๊ฐ์ผ๋ฉฐ ๊ฐ๋จํ๊ฒ ๊ตฌํ ํ ์ ์์ต๋๋ค.
์ while๋ฌธ์ ํด๋น ํ๋ ๋ถ๋ถ์ ์ฒ๋ฆฌ๋ฅผ ๊ธฐ๋ค๋ ค์ผ ํ๋ ๋์ (Rest ์ฒ๋ฆฌ , DB ์ฝ๊ธฐ , Download ๋ฑ)์ผ๋ก ๋์ฒดํ์ฌ
๊ฐ๋จํ๊ฒ ๊ตฌํํ๋ฉด ๋ฉ๋๋ค. ๐ค
๋ง์ง๋ง์ผ๋ก ์คํํ๋ฉด ์ฒจ๋ถํ๋ฉฐ ํฌ์คํ ๋ง์น๊ฒ ์ต๋๋ค.
์ค๋๋ ์ฆ์ฝํ์ธ์ :)