Task는 작업의 단위를 의미합니다. 프로그램에서는 내부에서 처리되는 하나의 로직을 의미할 수도 있습니다. 아주 좁은 의미에서는 var i = 10 + 10 과 같은 간단한 구문조차도 하나의 Task가 될 수 있습니다.
Task에는 동작하는 방식에 따라 동기와 비동기로 구분될 수 있는데 동기는 하나의 Task가 처리 중이면 다른 Task는 모두 기다려야 하는 방식이며 비동기는 여러 가지 Task가 동시적으로 작동할 수 있고, 작업이 끝나면 다른 Task가 종료되길 기다리지 않고 바로 다음 작업을 진행할 수 있다는 차이가 있습니다.
AsyncTask는 비동기 Task를 의미하며 스레드와 핸들러를 하나로 묶어 비동기적으로 Thread를 구현할 수 있습니다.
AsyncTask의 동작에 관한 간단한 에제를 만들어 볼텐데 그전에 아래 화면처럼 기본으로 배치된 TextView의 ID를 textView로 지정해 주세요.
AsyncTask를 구현하려면 우선 다음과 같이 AsyncTask클래스를 구현하는 메서드를 정의해야 합니다. AsyncTask는 doInBackground(), onProgressUpdater(), onPostExecute() 3개의 인터페이스 메서드를 구현해야 하는데 AsyncTask메서드에서 첫 번째 매개변수인 Params는 doInBackground() 메서드로, 두 번째 매개변수인 Progress는 onProgressUpdater() 메서드로, 마지막 세 번째 Result는 onPostExecute() 메서드로 전달됩니다. 예제에서는 Params에 Void를 지정해 어떠한 형식으로도 값을 받지 않도록 했으며 두 번째 Progrss는 Int형식으로, 마지막 Result는 String으로 문자열형의 매개변수를 받도록 했습니다.
val asyncTask = object : AsyncTask<Void, Int, String>() {
}
첫 번째로 doInBackground() 메서드를 구현합니다. doInBackground()는 실제 처리되어야 할 코드가 들어가며 해당 코드는 백그라운드 스레드에서 동작하게 됩니다. 예제에서의 코드는 간단한데 0부터 10까지 루프를 돌면서 현재의 i값을 표시하고자 하는 의도입니다.
val asyncTask = object : AsyncTask<Void, Int, String>() {
override fun doInBackground(vararg params: Void?): String {
for (i in 0..10) {
publishProgress(i)
Thread.sleep(1000)
}
return "10까지 완료"
}
}
두 번째로 onProgressUpdate() 메서드를 구현합니다. onProgressUpdate() 메서드는 위에서 작성한 doInBackground() 메서드에서 publishProgress() 메서드를 호출할 때마다 호출되는 메서드입니다. 참고로 예제에서 publishProgrsss() 메서드를 호출할 때 i변수를 전달하도록 했는데 이는 Progrss를 Int로 지정한 것과 형식이 일치하며 onProgressUpdate()에서 해당 값을 그대로 받아 처리할 수 있음을 확인할 수 있습니다.
또한 각 메서드의 매개변수를 가만히 보면 vararg로 되어 있는데 이는 타입에 해당하는 변수의 값을 "abc","def","ghi" 나 1,2,3처럼 쉼표(,)로 값을 구분해 전달할 수 있음을 의미합니다. 예제에서는 publishProgress(i)와 같이 정수 값을 하나만 보내고 있으므로 이 값을 받을 때는 values [0]처럼 처음의 값만 받아서 처리하게 되는 것입니다.
val asyncTask = object : AsyncTask<Void, Int, String>() {
override fun doInBackground(vararg params: Void?): String {
for (i in 0..10) {
publishProgress(i)
Thread.sleep(1000)
}
return "10까지 완료"
}
override fun onProgressUpdate(vararg values: Int?) {
super.onProgressUpdate(*values)
mytv.text = "${values[0]!!}"
}
}
마지막으로 onPostExecute() 메서드를 구현합니다. doInBackground() 메서드가 return을 통해 값을 반환하면 호출되는 메서드로서 이 역시 Result에서 지정한 String형식과 반환형식이 동일하며 메서드에서도 result의 값을 그대로 받아 처리하고 있음을 알 수 있습니다.
val asyncTask = object : AsyncTask<Void, Int, String>() {
override fun doInBackground(vararg params: Void?): String {
for (i in 0..10) {
publishProgress(i)
Thread.sleep(1000)
}
return "10까지 완료"
}
override fun onProgressUpdate(vararg values: Int?) {
super.onProgressUpdate(*values)
mytv.text = "${values[0]!!}"
}
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
mytv.text = result
}
}
위와 같이 AsyncTask가 구현되었으며 이제 excute() 메서드를 호출해 작업을 시작하도록 하면 됩니다. excute() 메서드를 호출할때는 아무런 값을 전달하지 않았는데 이는 Params를 Void로 처리한 것과 일치한다는 것을 말씀드립니다. 만약 Params에 특정 데이터 형식을 지정했다면 excute() 메서드를 호출할 때 지정한 형식과 일치하는 데이터를 전달해야 합니다.
class MainActivity : AppCompatActivity() {
private lateinit var mytv: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
mytv = findViewById(R.id.textView)
asyncTask.execute()
}
val asyncTask = object : AsyncTask<Void, Int, String>() {
override fun doInBackground(vararg params: Void?): String {
for (i in 0..10) {
publishProgress(i)
Thread.sleep(1000)
}
return "10까지 완료"
}
override fun onProgressUpdate(vararg values: Int?) {
super.onProgressUpdate(*values)
mytv.text = "${values[0]!!}"
}
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
mytv.text = result
}
}
}
'Mobile > Kotlin' 카테고리의 다른 글
[Kotlin] 포어그라운드(Foreground) 서비스 (0) | 2021.01.08 |
---|---|
[Kotlin] 서비스(Service) (2) | 2021.01.07 |
[Kotlin] 프로세스(Process)와 스레드(Thread) (0) | 2021.01.05 |
[Kotlin] 사진저장하고 가져오기 (4) | 2021.01.05 |
[Kotlin] 카메라 사용하기 (0) | 2020.12.31 |