Kotlin의 Coloutine에서 AsyncTask와 동일한 기능 구현

환경 확인


이 글의 내용은 다음과 같은 환경에서 검증되었다.
  • Java:open jdk 1.8.0_152
  • Android Studio 3.0
  • CompileSdkVersion:26
  • MinSdkVersion:21
  • TargetSdkVersion:26
  • BuildToolsVersion:26.0.2
  • gradle:3.0.0
  • AsyncTask


    AsyncTask는 Android에서 비동기식 작업을 수행하는 유틸리티 클래스 중 하나입니다.
    자세한 내용은 아래 사이트를 참조하십시오.
    ( https://developer.android.com/reference/android/os/AsyncTask.html)

    Coroutine


    Coroutine는 Kotlin1.1 실험에서 도입된 비동기 처리를 쉽게 실현하는 기능이다.
    async/await/launch 등 함수를 이용하여 비동기 처리를 실현합니다.
    (이 글은 async 함수를 통해 비동기 처리를 실현한다.)
    함수에 대한 상세한 정보는 아래 사이트를 참조하십시오.
    ( https://github.com/Kotlin/kotlinx.coroutines)
    Cooutine에서 AsyncTask와 같은 기능을 실현할 때의 차이를 확인하기 위해 본고는 Cooutine의 상세한 설명을 생략하였다.
    또한 취소 처리를 실시하지 않았다.

    예제 응용 프로그램


    완료 이미지


    이 글에서 만든 샘플 응용 프로그램의 완성 인상은 아래 그림과 같다.

    예제 응용 프로그램 세부 정보


    시작 버튼을 누르면 TextView 디스플레이가 시작됩니다.그리고 0.8초마다 TextView에 1-10개의 값을 계산합니다.계수가 끝나면 TextView 디스플레이가 종료됩니다.

    소스 코드 및 설명


    예시 프로그램은 다음과 같은 파일로 구성되어 있다.
    (항목이 생성된 후 변경되지 않은 선언 파일 등을 생략합니다.)

    파일 목록


    레이아웃 디자인

  • activity_main.xml
  • Activity

  • MainActivity.kt(AsyncTask에 설치)
  • MainActivity.kt(Coroutine 설치를 통해)
  • Gradle

  • build.gradle(app)
  • Gradle


    Android에서 Coroutine를 이용하기 위해build.gradle (app) 의 dependencies에 다음 줄을 추가합니다.
     compile "org.jetbrains.kotlinx:kotlinx-coroutines-android:0.19.3"
    

    레이아웃 디자인


    최종 레이아웃의 이미지는 다음과 같습니다.

    activity_main.xml


    전체 화면의 판면 디자인 파일의 내용은 다음과 같다.
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context="jp.co.casareal.afterasync.MainActivity">
    
        <TextView
            android:id="@+id/text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            android:textSize="30sp" />
    
        <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="スタート"
            android:textSize="30sp" />
    </LinearLayout>
    

    Activity


    MainActivity.kt(AsyncTask에서 수행)


    AsyncTask에서 예제 응용 프로그램을 실행할 때의 활성 소스 코드는 다음과 같습니다.
    MainActivity
    package jp.co.casareal.asyncbefor
    
    import android.os.AsyncTask
    import android.os.Bundle
    import android.support.v7.app.AppCompatActivity
    import kotlinx.android.synthetic.main.activity_main.*
    
    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            button.setOnClickListener {
                MyAsyncTask().execute()
            }
        }
    
        inner class MyAsyncTask : AsyncTask<Void, Int, Void>() {
    
            override fun onPreExecute() {
                text.setText("始めます")
                Thread.sleep(800)
            }
    
            override fun doInBackground(vararg param: Void?): Void? {
                for (i in 1..10) {
                    publishProgress(i)
                    Thread.sleep(800)
                }
                return null
            }
    
            override fun onProgressUpdate(vararg values: Int?) {
                text.setText(values[0].toString())
            }
    
            override fun onPostExecute(result: Void?) {
                text.setText("終わります")
            }
    
        }
    }
    

    구현 지침


    AsyncTask를 상속하는 클래스는 내부 클래스로 정의됩니다.
    onPreExecute 방법, onProgress Update 방법, onPostExecute 방법은 UI를 변경할 수 있는 메인 라인에서 실행됩니다.따라서 예제 코드는 TextView의 속성을 변경합니다.

    MainActivity.kt(Coroutine을 통한 구현)

    package jp.co.casareal.afterasync
    
    import android.os.Bundle
    import android.support.v7.app.AppCompatActivity
    import kotlinx.android.synthetic.main.activity_main.*
    import kotlinx.coroutines.experimental.Deferred
    import kotlinx.coroutines.experimental.android.UI
    import kotlinx.coroutines.experimental.async
    
    class MainActivity : AppCompatActivity() {
    
        var job: Deferred<Unit>? = null
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            button.setOnClickListener {
                // async関数の戻り(Deferred型)を受け取る
                job = async {
                    // myTaskメソッドの呼び出し
                    myTask()
                }
            }
        }
    
        private suspend fun myTask() {
            // onPreExecuteと同等の処理
            async(UI) {
                text.text = "始めます"
            }
    
            // doInBackgroundメソッドとonProgressUpdateメソッドと
            // 同等の処理
            Thread.sleep(800)
            for (i in 1..10) {
                async(UI) {
                    text.text = i.toString()
                }
                Thread.sleep(800)
            }
    
            // onPostExecuteメソッドと同等の処理
            async(UI) {
                text.text = "終わります"
            }
    
        }
    }
    

    구현 지침


    async 함수를 사용하여 비동기 처리를 실현합니다.async 함수의 정의는 아래 사이트를 참조하십시오.
    ( https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/async.html)
    예시 코드에서 다음과 같은 두 가지 async 함수의 기술 방법이 나타났다.
    async 함수
    import kotlinx.coroutines.experimental.async
    
    async{・・・処理・・・}
    
    상기 방법을 사용하여 설명하면'주 라인이 아닌 라인'에서 처리됩니다.따라서 UI는 변경할 수 없습니다.
    UI 변경 등의 작업을 수행하면 CalledFromWrongThreadException이 발생합니다.이상이 발생하면 자대연목소의 처리가 끝나지만 부대연목소의 처리는 계속된다.
    import kotlinx.coroutines.experimental.async
    import kotlinx.coroutines.experimental.android.UI
    
    async(UI) {・・・処理・・・}
    
    async 함수 매개 변수를 처리할 라인을 지정할 수 있습니다.
    상술한 방법으로 설명하면 메인 라인에서 처리됩니다.따라서 UI 변경 등이 가능합니다.
    suspend 수식자
    콜딩에서 호출하는 방법과 함수는 반드시'suspend'수식자를 가지고 있어야 한다.
    private suspend fun myTask() {・・・処理・・・}
    

    총결산


    Coroutine에서 AsyncTask를 실행하면 코드의 양이 줄어들고 가독성도 높아집니다.

    좋은 웹페이지 즐겨찾기