728x90
반응형
Coroutine : 스레드를 멈추지 않고 비동기 처리
하나의 스레드안에 여러개의 코투틴 설계
코틀린 언어에서 제공해준다. 안드로이드 기술은 아니다.
(Java는 코루틴을 지원해주지 않는다. 언어에서 지원해줘야 쓸수있다.)
한 worker당 여러개씩 작업하게 만들어주는 경량스레드
(↔ 스레드는 한 worker가 작업 공간을 바꿔가면서 하는 느낌)
1. 코루틴을 구동하는 2개의 Scope(범위)가 존재함.
(1) GlobalScope : 앱 전체의 생명주기와 함께 관리됨 (앱이 끝날때까지 계속 작업한다. 사용성이 그렇게 좋진않음. )
(2) CoroutineScope : 버튼 클릭 등 특정 이벤트 순간에 해야할 Job을 위해 실행되는 범위 >> 네트워크 통신, DB CRUD , 특정 연산 등
GlobalScope
GlobalScope.launch {
for(n in 0..9){
Log.d("TAG","n:$n - ${Thread.currentThread().name}") //Thread.currentThread().name 스레드 이름이 누구니?
//이걸 메인스레드에게 던지지않는다 누구에게 던질까? DefaultDispatcher-worker-1
//Thread.sleep(500) 는 요리사를 실제로 잠재움
delay(500)
}
} //이 for문과 아래 토스트는 동시에 작업된다. 토스트+숫자세는것이 동시에 됨. 경량스레드 역할
Toast.makeText(this, "hi", Toast.LENGTH_SHORT).show()
}
CoroutineScope
비동기 작업으로 Corutine 실행
//CorutineScope는 GlobalScope와 다르게 해당 작업을 어떤 스레드에게 보낼지 결정하는 Dispatcher[디스패처]를 지정해야 함.
//보통 1,2,3을 많이 쓰고, IO를 많이쓰게될것이다.
//Dispatcher의 종류
//(1) Dispatchers.Defalut - 기본 스레드풀의 스레드를 사용 [cpu작업이 많은 연산작업에 적합]
//(2) Dispatchers.IO - DB나 네트워크 IO 스레드를 사용 [파일입출력, 서버작업에 적합]
//(3) Dispatchers.Main - MainThread를 사용한다. [ UI작업 등에 적합 ]
//(4) Dispatchers.Unconfined - 조금 특별한 디스패처 [해당 코루틴을 호출하는 스레드에서 실행]
binding.btnCs.setOnClickListener {
//(1) Dispatchers.Defalut 사용해보기 -> 원래 이거 되면 안되는데 된다...
CoroutineScope(Dispatchers.Default).launch {
//context는 저장소
for(n in 0..9){
Log.d("TAG","n: $n - ${Thread.currentThread().name}")
binding.tv.text = "n : $n"
//작업을 한 스레드의 이름 : DefaultDispatcher-worker-1
delay(500)
}
}
Toast.makeText(this, "hi~~", Toast.LENGTH_SHORT).show()
}
//실습 4)
binding.btnMain.setOnClickListener {
CoroutineScope(Dispatchers.Main).launch {
for (n in 0..9) {
Log.d("TAG", "n: $n - ${Thread.currentThread().name}")
binding.tv.text = "n : $n"
//작업을 한 스레드의 이름 : DefaultDispatcher-worker-1
delay(500)
}
}
Toast.makeText(this, "hi~~", Toast.LENGTH_SHORT).show()
//하나의 스레드가 코루틴 여러개를 할수있다.
}
//실습 5)
binding.btnServerMain.setOnClickListener {
CoroutineScope(Dispatchers.Main).launch {
//네트워크 이미지 불러오기 -->에러! 메인스레드는 네트워크 작업 불가능
val url = URL("https://cdn.pixabay.com/photo/2023/06/01/06/22/british-shorthair-8032816_640.jpg")
val bm:Bitmap = BitmapFactory.decodeStream(url.openStream())
binding.iv.setImageBitmap(bm)
}
}
//실습 6)
binding.btnIo.setOnClickListener {
CoroutineScope(Dispatchers.IO).launch {
val url = URL("https://cdn.pixabay.com/photo/2023/06/01/06/22/british-shorthair-8032816_640.jpg")
val bm:Bitmap = BitmapFactory.decodeStream(url.openStream())
//에러!! 바로꺼짐..! 입출력 전용 스레드는 UI 변경 불가
//밑에 처럼 메인과 같이 가는 함수를 써줘야한다.
withContext(Dispatchers.Main){
binding.iv.setImageBitmap(bm)
}
}
}
//실습 7)
binding.btn6.setOnClickListener {
CoroutineScope(Dispatchers.Default).launch {
//작업 1
launch {
for(n1 in 1000..1010){
Log.d("TAG","n1:$n1")
delay(500)
}
}
//작업 2
launch {
for(n2 in 1000..1010){
Log.d("TAG","n2:$n2")
delay(500)
}
}
}
}//btn6
//실습 8) join을 하게되면 순차적으로 출력된다.
binding.btn7.setOnClickListener {
CoroutineScope(Dispatchers.Default).launch {
//작업 1
launch {
for(n1 in 1000..1010){
Log.d("TAG","n1:$n1")
delay(500)
}
}.join()
//작업 2
launch {
for(n2 in 1000..1010){
Log.d("TAG","n2:$n2")
delay(500)
}
}.join()
}
}
binding.btn8.setOnClickListener {
CoroutineScope(Dispatchers.Default).launch {
someTask()
}
}
binding.btn9.setOnClickListener {
//스코프를 런치하면 참조할수있다. 상단 멤버변수에 job을 만들어준다.
job = CoroutineScope(Dispatchers.Default).launch {
for (n in 300..310){
Log.d("TAG","n:$n")
delay(500)
}
}
}
binding.btn10.setOnClickListener {
job?.cancel()
}
//근데 이건 내가 일일히 작업하는것, 안드로이드 생명주기를 알아서 보고 처리하는 녀석
}
}//onCreate
suspend fun someTask(){
//코루틴 스코프 범위 밖에서 코루틴의 기능을 사용할 때 함수를 suspend 함수로 만들면 해결
for(n in 1000..1010){
Log.d("TAG","someTask : $n")
delay(500) //딜레이는 코루틴안에서만 써야한다. 특정 메소드에서 코루틴의 기능을 못쓰게된다.. 이때 쓸수있는!!! suspend
}
2. LifeCycleScope / ViewModelScope
안드로이드의 액티비티 or 프래그먼트의 생명주기에 따라 반응하는 코루틴
별도 라이브러리를 추가해줘야한다.
안드로이드 31버전부터는 activity를 꺼도 앱이 완벽하게 꺼지지 않는다. onBackPressed에 finish()를 해야 온전하게 다 꺼진다.
private fun clickBtn1(){
CoroutineScope(Dispatchers.Default).launch {
for(n in 0..20){
Log.d("TAG","coroutine scope : $n")
delay(500)
}
}
}
private fun clickBtn2(){
//android의 라이프사이클에 같이 제어되는 LifeCycleScope
//lifecycle
//this 가 생략... [onCreate()~~onDestroy()까지늬 액티비티 라이플사이클 ]
//31버전 이상부터는 액티비티를 꺼도 안꺼진다. 그래서 무조건 finish를 해줘야햔다.
lifecycleScope.launch {
for(n in 110..120){
Log.d("TAG","Lifecycle scope : $n")
delay(500)
}
}
}
override fun onBackPressed() {
finish()
}
private fun clickBtn3(){
//[onResume() ~~ onPause()동안에만 코루틴 동작 .. onPause()만 되면 자동 일시정지. 다시 onResume()되면 자동으로 이어서 실행]
lifecycleScope.launchWhenResumed {
loopTask()
}
}
suspend fun loopTask(){
for(n in 200..210){
Log.d("TAG","lifecycle scope when resume : $n")
delay(500)
}
}
728x90
반응형
'Android Kotlin' 카테고리의 다른 글
Android Studio(Kotlin) 스키마 SCHEMA (0) | 2023.06.17 |
---|---|
Android Studio 보일러플레이트 (0) | 2023.06.12 |
AndroidStudio Jetpack LiveData (1) | 2023.06.02 |
Android Studio AutoCompleteTextView 클릭 시, Fragment로 전환하기 (0) | 2023.04.03 |
Android Studio strings.xml 사용하기 (0) | 2023.04.02 |