Deperecated/Android_강의

안드로이드 - AsyncTask

누알라리 2020. 2. 17. 23:53
1. 개요

스레드를 사용하면서 UI 객체에 접근하려면 핸들러를 통하면 된다. 하지만 Message 객체를 사용할 경우 코드가 길어진다는 문제가 생긴다. 

AsyncTask는 하나의 클래스 안에 스레드로 동작하는 부분과 UI 객체에 접근하는 부분을 함께 넣을 수 있도록 합니다.

이 때문에 스레드를 사용하는 하나의 작업 단위가 AsyncTask라는 하나의 클래스로 만들어질 수 있다.

 

1. AsyncTask

- AsyncTask는 비 동기 처리를 위해 제공되는 클래스 이다.

- 개발자가 발생 시키는 쓰레드와 핸들러의 조합으로 쓰레드 운영 중 화면 처리가 가능했던 구조를 클래스로 제공하는 것이다.

- AsyncTask를 사용하면 개발자가 발생시키는 일반쓰레드와 화면 처리를 위해 MainThread를 이용하는것을 조합하여 작업이 가능하다.

 

 

 

출처: https://www.edwith.org/boostcourse-android/lecture/17087/

2. 오버라이드 주요 메서드

1. onPreExeCute()

- doInBackground 메서드가 호출되기 전에 호출되는 메서드.

- Main Thread가 처리한다.

- 5초 이상의 작업을 하면 안되고, 화면 처리가 가능하다.

 

2. doInBackground()

- 일반 Thread에서 처리한다.

- 네트워크 작업 or 5초 이상 걸리는 작업을 이 메서드에서 처리한다.

 

3. onProgressUpdate()

- doInBackground 메서드에서 publishProgress 메서드를 호출하면 Main Thread가 처리하는 메서드.

- doInBackground 메서드 내에서 화면 처리가 필요할 때 사용한다.

 

4. onPostExcute()

- doInBackground 메서드 수행 완료 후 호출.

- Main Thread가 처리한다.

 

-> 스레드안에서 실행될 코드는 doInBackground() 에 넣어두고 UI에 접근할 코드는 나머지에 넣어둔다.

-> AsyncTask도 스레드를 실행하는 것과 같기 때문에 스레드 안에서 실행될 대부분의 코드는 doInBackground() 안에 들어가있게 되며 중간중간 화면에 표시하기 위한 코드 실행을 위해 onProgressUpdate()가 호출되는 것이다.

-> onProgressUpdate()는 doInBackground()안에서 publishProgress()가 호출될 때마다 자동으로 호출된다.

 

3. AsyncTaskClass 오버라이딩

1. inner class AsyncTaskClass : AsyncTask<Int, Long, String>() 

// 제네릭 타입을 3개 지정해주어야 한다.
// 제네릭1) excute() 매개변수 타입
// 제네릭2) publishProgress() 매개변수 타입
// 제네릭3) doInBackground()의 반환 타입 이자 onPostExcute의 매개변수 타입

 

2. onCreate()에서 sync.excute() 호출로 AsyncTask 가동.

// execute()의 매개변수는 그대로 doInBackground()의 매개변수로 넘어간다.

 

3. onPreExecute()

4. doInBackground()

 

// 화면 처리가 필요하다면.....

5.  doInBackground() 에서 publishProgress() 호출.

 

6.  onProgressUpdate()

// publishProgress()의 매개변수가 전달됨 화면 처리.

 

7. doInBackground()의 작업이 끝나면 반환값을 onPostExecute()에 전달하며 종료.

 

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


        button.setOnClickListener { view ->
            var time = System.currentTimeMillis()
            textView.text = "버튼 클릭 : ${time}"
        }

        var sync = AsyncTaskClass()

        // 1. AsyncTask 가동. execute()의 매개변수는 그대로 doInBackground()의 매개변수로 넘어간다.
        sync.execute(10, 20)
    }


    // 제네릭 타입을 3개 지정해주어야 한다.
    // 제네릭1) excute() 매개변수 타입
    // 제네릭2) publishProgress() 매개변수 타입
    // 제네릭3) doInBackground()의 반환 타입 이자 onPostExcute의 매개변수 타입
    inner class AsyncTaskClass : AsyncTask<Int, Long, String>() {

        // doInBackground 메서드가 호출되기 전에 딱 한 번 호출되는 메서드.  Main Thread가 처리한다.
        override fun onPreExecute() {
            super.onPreExecute()

            textView2.text = " AsyncTask 가동 ";
        }

        //  일반 Thread에서 처리한다.  네트워크 작업 or 5초 이상 걸리는 작업을 이 메서드에서 처리한다.
        // 1. execute()의 매개변수는 그대로 doInBackground()의 매개변수로 넘어간다.
        override fun doInBackground(vararg params: Int?): String {

            // 2.
            // varag params에는 ?가 붙어서 NULL을 허용하지만, 정수 값을 뽑아낼거기 때문에 NULL을 허용하면 안되므로
            // NULL을 허용하는 변수를 NULL을 허용하지 않는 변수에 넣고싶을 때는 느낌표2개(!!)을 붙여주면 된다.
            var a1 = params[0]!!
            var a2 = params[1]!!

            for (idx in 0..9) {
                SystemClock.sleep(100)

                a1++
                a2++

                // 3.
                // 이렇게하면 되긴하는데 WrongThread 경고가 뜬다. 안드로이드는 일반 쓰레드에서 화면 처리를 하면 경고를 보낸다. 따라서 좋은 코드가 아님.
                //textView2.text = " ${idx} : ${a1}, ${a2}"
                
                // 4.
                // doInBackground() 에서 화면처리를 하려면 onProgressUpdate() 함수가 필요하고, 그 함수는 publishProgress()로 호출할 수 있다.
                // publishProgress(varags 변수) 매개변수가 onProgressUpdate(varags 변수)로 전달된다. 값 여러개 전달하면 배열로 만들어져 전달된다.
                // 메인쓰레드가 한가할 때 publishProgress()를 호출해준다.
                var time = System.currentTimeMillis()
                publishProgress(time)

            }

            return "지존현지"
        }

        // 4.
        // doInBackground 메서드에서 publishProgress 메서드를 호출하면 Main Thread가 처리하는 메서드. doInBackground 메서드 내에서 화면 처리가 필요할 때 사용한다.
        override fun onProgressUpdate(vararg values: Long?) {
            super.onProgressUpdate(*values)

            textView2.text = "Async : ${values[0]}"
        }

        // 5.
        // doInBackground()의 반환 타입이 매개변수로 넘어온다.
        // doInBackground 메서드 수행 완료 후 호출. MainThread가 처리한다.
        override fun onPostExecute(result: String?) {
            super.onPostExecute(result)

            textView2.text = result
        }
    }

 

4. varag 가변형 매개변수

- 가변형 매개변수. 값을 N개 넘겨주면 N개짜리 배열이 만들어져서 넘어간다.

 

https://developer.android.com/reference/android/os/AsyncTask.html