Vintage appMaker의 Tech Blog

[kotlin] coroutine내에서 Flow 사용 본문

Source code or Tip/Android(Java, Kotlin)

[kotlin] coroutine내에서 Flow 사용

VintageappMaker 2021. 3. 15. 10:20

 

 

⚽ Flow 공식문서 

 

Asynchronous Flow - Help | Kotlin

 

kotlinlang.org

flow는 coroutine내에서 스트림과 같은 순차적 프로그래밍을 할 때 사용한다.
주로 네트웍 통신에서 유용하게 사용된다.
flow{}내에서 emit으로 값을 전달하면 collect에서 받아 처리한다.


- 동영상 플레이하면서 썸네일 리스트를 보여줄 때
- 한 화면에 다수의 서버통신을 해야 할 때

사용하면 효과적으로 이용할 수 있다. 

아래 예제는 jsoup을 사용하므로 intelliJ 프로젝트 build.gradle.kts 파일에 다음과 같이 jsoup 정보를 추가한다.  

implementation ("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2")
implementation ("org.jsoup:jsoup:1.13.1")

⚽ 예제

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import org.jsoup.Jsoup

// build.gradle.kts의 dependancy에
// implementation ("org.jsoup:jsoup:1.13.1")
// 추가

// Android에서는 runBlocking(점유율)과 GlobalScope(전역적)는 사용하지 않는 것이 좋다.
fun main() = runBlocking{
    // 1, 2에서 동시 작업을 통해 imgList와 종료정보를 공유함
    var imgList   = mutableListOf<String>()
    var bComplete : Boolean = false;
    var onComplete :() -> Unit  = { bComplete = true}

    // 1. 네트웍을 통해 정보가져오기(imgList 저장)
    getImageInfoFromNetwork("http://vintageappmaker.com", imgList, onComplete)

    // 2. UI 작업(imgList 보여주기)
    launch {
        (0..100).forEach {
            println (">> \uD83C\uDFA8 [UI Working].. #$it")
            println (">> \uD83C\uDFA8 imgList count =>  ${imgList.count()}")
            delay(500)

            if(bComplete) cancel()
        }
    }

    // 3. 결과물 출력위한 대기
    delay(1000 * 10)
}

fun getImageInfoFromNetwork(url : String, imgList : MutableList<String>, onComplete : () -> Unit) {
    CoroutineScope(Dispatchers.IO).launch {
        flow{
            var doc = Jsoup.connect(url).get()
            var lst = doc.getElementsByTag("img")
            lst.forEach {
                var sUrl = it.attr("src")
                emit(sUrl)
                delay(400)
            }

            // 모두 처리했음
            emit(true)
        }.collect {
            if (it is String ) {
                println("[network] image download complete => $it")
                imgList.add(it)
            } else {
                // 종료 callback 호출
                onComplete()
            }
        }
    }
}

BUILD SUCCESSFUL in 6s
1 actionable task: 1 executed
> Task :compileKotlin UP-TO-DATE
> Task :compileJava NO-SOURCE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE

> Task :AsynctestKt.main()
>> 🎨 [UI Working].. #0
>> 🎨 imgList count =>  0
>> 🎨 [UI Working].. #1
>> 🎨 imgList count =>  0
>> 🎨 [UI Working].. #2
>> 🎨 imgList count =>  0
>> 🎨 [UI Working].. #3
>> 🎨 imgList count =>  0
>> 🎨 [UI Working].. #4
>> 🎨 imgList count =>  0
>> 🎨 [UI Working].. #5
>> 🎨 imgList count =>  0
>> 🎨 [UI Working].. #6
>> 🎨 imgList count =>  0
[network] image download complete => http://vintageappmaker.com/wp-content/uploads/2015/03/cropped-logo.png
>> 🎨 [UI Working].. #7
>> 🎨 imgList count =>  1
[network] image download complete => http://vintageappmaker.com/wp-content/uploads/2018/03/if_Coding_Icons_-_LINE-13_1024945.png
[network] image download complete => http://vintageappmaker.com/wp-content/uploads/2018/03/if_property-agent-005_1851811.png
>> 🎨 [UI Working].. #8
>> 🎨 imgList count =>  3
[network] image download complete => http://vintageappmaker.com/wp-content/uploads/2018/03/if__android_2006477.png
>> 🎨 [UI Working].. #9
>> 🎨 imgList count =>  4
[network] image download complete => http://vintageappmaker.com/wp-content/uploads/2020/11/화면-캡처-2020-11-03-211550.jpg
>> 🎨 [UI Working].. #10
>> 🎨 imgList count =>  5
[network] image download complete => http://vintageappmaker.com/wp-content/uploads/2019/01/2019-01-07-160810.png
>> 🎨 [UI Working].. #11
>> 🎨 imgList count =>  6
[network] image download complete => http://vintageappmaker.com/wp-content/uploads/2019/01/2019-01-04-193621.png
[network] image download complete => http://vintageappmaker.com/wp-content/uploads/2018/12/2018-12-22-143435.png
>> 🎨 [UI Working].. #12
>> 🎨 imgList count =>  8
[network] image download complete => http://vintageappmaker.com/wp-content/uploads/2018/07/36965822_941243062713983_486681895568932864_n.jpg
>> 🎨 [UI Working].. #13
>> 🎨 imgList count =>  9
[network] image download complete => http://vintageappmaker.com/wp-content/uploads/2018/03/if__android_2006477.png
>> 🎨 [UI Working].. #14
>> 🎨 imgList count =>  10
[network] image download complete => http://vintageappmaker.com/wp-content/uploads/2018/03/IOS.gif
[network] image download complete => http://vintageappmaker.com/wp-content/uploads/2018/03/fastcampus.gif
>> 🎨 [UI Working].. #15
>> 🎨 imgList count =>  12
[network] image download complete => http://vintageappmaker.com/wp-content/themes/zerif-lite/images/blank-latestposts.png
>> 🎨 [UI Working].. #16
>> 🎨 imgList count =>  13
[network] image download complete => http://vintageappmaker.com/wp-content/uploads/2018/03/Screenshot3.png
>> 🎨 [UI Working].. #17
>> 🎨 imgList count =>  14
>> 🎨 [UI Working].. #18
>> 🎨 imgList count =>  14

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.7/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 11s
2 actionable tasks: 1 executed, 1 up-to-date
오전 10:07:55: Task execution finished 'AsynctestKt.main()'.

 

전체소스:

 

VintageAppMaker/KotlinOnepointLesson

Kotlin을 빠르게 시작하기 위한 소스정리. Contribute to VintageAppMaker/KotlinOnepointLesson development by creating an account on GitHub.

github.com

 

Comments