개발일지

[Android] AsyncTask 본문

Android

[Android] AsyncTask

강강강 2021. 7. 6. 18:56

########This class was deprecated in API level 30.#########

[AsyncTask<Params, Progress, Result>]

Params : doInBackground 파라미터 타입이며 execute 메소드 인자값

Progress: doInBackground 작업시 진행단위의 타입으로 onProgressUpdate 의 파라미터 타입 

Result: doInBackground의 리턴값으로 onPostExecute 파라미터 타입

[사용법 4단계]

1. onPreExecute()

: task 실행하기 전 UI thread 를 발생시키고 싶을 때 사용합니다.

doInBackground() 실행되기 전에 호출되기때문에 보통 프로그레스바나 다이얼로그띄우는 코드를 넣습니다. 

 

2. doInBackground(Params...)

: onPreExecute() 가 끝나는 즉시 백그라운드 스레드에서 실행됩니다.

이 단계는 오랜 시간이 걸리는 백그라운드 작업을 수행하는데 사용됩니다.

publishProgress(Progress) 함수를 사용하여 하나 이상의 프로그레스를 퍼블리쉬 할  수 있습니다. 

 

3. onProgressUpdate(Progress...)

: doInBackground 에서 publishProgress(Progress) 가 호출되었을 때 발생하는 함수입니다. 

백그라운드 작업은 계속 실행되고 있는 동안 사용자 인터페이스에 진행상황을 표시하는데 사용됩니다. 

예를들어 프로그레스바 진행상태를 업데이트할 때 사용됩니다.

 

4. onPostExecute(Result)

: 백그라운드 task 가 완료되고 UI thread 에서 호출됩니다. doInBackground() 리턴값은 이 함수의 매개변수로 전달됩니다.

 

 

[AsyncTask 메소드] 

1. excute() 메소드는 생성한 Asynctask 상속한 객체를 실행시켜서 이 객체는 이때부터 백그라운드 작업을 수행하기 시작하고 필요한 경우에는 그 결과를 메인 스레드에서 실행하므로 UI객체에 접근 할 수있습니다. 

 

2. doInBackground()는 새로 만들어진 스레드, 즉 백그라운드 작업을 할 수 있습니다. 그리고 excute() 메소드를 호출할 때 사용되니 파라미터를 배열로 전달받을 수 있습니다.

중간중간마다 UI객체에 접근할려면 메인스레드에서 해야하므로 publishProgress() 를 호출해 onProgressUpdate(Progress...)를 호출해 메인스레드에서 UI작업이 가능합니다.

 

3. onPreExcute(), onProgressUpdate(), onPostExcute()는 메인 스레드에서 실행되므로 UI 객체에 자유롭게 접근이 가능합니다.(초기화 작업에 사용)

-onPreExecute(): 작업이 실행되기 직전에 UI 스레드에 의해 호출됩니다. 일반적으로 UI 초기화와 같이, "비동기(Asynchronous) 실행" 작업에 대한 초기화 과정을 수행하는 메서드

-onProgressUpdate()는 백그라운드 작업의 진행하면서 중간 중간에 UI객체에 접근하는 경우 사용. 즉 doInBackground()가 진행중에 사용됩니다.

이 메소드가 호출될려면 doInBackground에서 publishProgress()메소드를 호출해야 합니다.

-onPostExcute()는 백그라운드 작업이 끝나면 호출이 되고 메모리 리소를 해체하는 작업을 주로합니다. 백그라운드 작업의 결과를 매개변수로 전달받을 수도 있습니다.

 

4. onCancelled()는 AsyncTask객체를 cancel()로 종료시키면 호출되는 메소드입니다.

 

즉, doInBackground()에서 백그라운드 작업을 하면되고 이 메소드빼고 다 메인스레드작업이고 UI접근이 가능합니다.

 

override fun doInBackground(vararg params: String): String {
    var output: JSONObject? = null
    var body = JSONObject()
    body.put("TASKID", params[0])
    body.put("ACTION", params[1])
    body.put("INPUT", params[2])

    try {
        val url = URL(URL)
        val postconn = url!!.openConnection() as HttpURLConnection
        postconn.requestMethod = "POST"
        postconn.setRequestProperty("Content-type", "application/json")
        postconn.doOutput = true
        var os: OutputStream = postconn.outputStream
        os.write(body.toString().toByteArray())
        os.flush()
        os.close()

        if (postconn.responseCode == HttpURLConnection.HTTP_CREATED) {
            do {
                if (isCancelled) {
                    return cancelObj
                }
                val url = URL("$URL" + params[0])
                val getconn = url!!.openConnection() as HttpURLConnection
                getconn.requestMethod = "GET"
                getconn.setRequestProperty("Content-type", "application/json")
                getconn.doInput = true

                if (getconn.responseCode == HttpURLConnection.HTTP_OK) {
                    var tmp = InputStreamReader(getconn.inputStream, "UTF-8")
                    var reader = BufferedReader(tmp)
                    var line: String = reader.readLine()
                    output = JSONObject(line)

                    if (output.getString("STATUS") == "DONE") {
                        return output.toString()
                    }
                    Thread.sleep(1000)
                } else {
                    throw error("Not HTTP status code 200, Current status: " + getconn.responseCode)
                }
            } while (true)
        } else {
            throw error("Not HTTP status code 201, Current status: " + postconn.responseCode)
        }
    } catch (e: Exception) {
        e.printStackTrace()
        Log.e("Exception", e.message)
    }
    return output.toString()
}

override fun onPostExecute(result: String?) {
        super.onPostExecute(result)
        listener.setResult(result)
    }

    override fun onCancelled() { 
        super.onCancelled()
        listener.setResult(cancelObj)
    }

 

아래 코드는 execute 를 통해 AsyncTask 를 호출하는 코드이다. 

execute().get() 이라는 함수를 통해 doInBackground 의 결과값을 리턴받을 수 있는데 get()을 쓸 경우 모든 스레드가 멈추기때문에 UI 작업을 할 수 없게 된다. AsyncTask 중간에 다이얼로그나 프로그레스바같은 UI 작업을 해야한다면  get()을 안쓰는게 답이다.

RemoteInteractionTask task = new RemoteInteractionTask((DialogListener) context);
btn.setOnClickListener(v -> {
    task.cancel(false);
});
task.execute(result.getId(), result.getActionCode(), result.data().toString());

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

 

AsyncTask  |  Android Developers

 

developer.android.com