티스토리 뷰

Mobile/Android

[Android] AsyncTask

춘햄 2022. 4. 7. 08:51

직전에 확인했던 메시지 객체를 메인 스레드에서 별도의 스레드로 전송하는 코드를 확인해보면, 생각보다 복잡하다는 느낌이 든다. 

 

핸들러를 사용하지 않고 좀 더 간단하게 동일한 기능을 수행하도록 Thread 코드를 작성할 수도 있는데, AsyncTask 객체를 사용하면 된다.

 

AsyncTask 클래스를 상속하여 새로운 클래스를 만들면 그 안에 스레드를 위한 코드와 UI  접근 코드를 함께 넣을 수 있다. 

 

AsyncTaSK 객체를 만들고 excute() 메서드를 실행하면 이 객체는 정의된 백그라운드 작업을 수행하고 필요한 경우에 그 결과를 메이느스레들에서 실행하기 때문에 UI 객체에 접근하는 데 문제가 없다.

 

다음은 AsyncTask를 이용한 작업 방식을 그림으로 나타낸 것이다.

 

 

AsyncTask 에 정의된 주요 메서드들은 다음과 같다.

메서드 명 설명
doInBackground 새로 만든 스레드에서 백그라운드 작업을 수행한다. excute() 메서드를 호출할 때 사용된 파라미터를 배열로 전달받는다.
onPreExcute 백그라운드 작업을 수행하기 전에 호출된다. 메인 스레드에서 실행되며 초기화 작업에 사용된다.
onProgressUpdate 백그라운드 작업의 진행 상태를 표시하기 위해 호출된다. 작업 수행 중간 중간에 UI 객체에 접근하는 경우에 사용된다. 이 메서드가 호출되도록 하려면 백그라운드 작업 중간에 publishProgress() 메서드를 호출해야 한다.
onPostExecute 백그라운드 작업이 끝난 후에 호출된다. 메인 스레드에서 실행되며 메모리 리소스를 해제하는 등의 작업에 사용된다. 백그라운드 작업의 결과는 Result 타입의 파라미터로 전달된다.

또한 cancel 메서드를 호출하여 작업을 취소할 수 있는데, 이 메서드로 작업을 취소했을 때는 onCancelled() 가 호출된다. 

getStatus() 메서드를 호출하여 현재 작업의 진행 상황을 확인할 수도 있다.

 

예제로 한번 확인해보자.


◎MainActivity.java

package com.example.sampleasynctask;

import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    BackgroundTask task;
    int value;

    ProgressBar progressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        progressBar = findViewById(R.id.progressBar);

        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                task = new BackgroundTask();
                task.execute();
            }
        });

        Button button2 = findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                task.cancel(true);
            }
        });
    }

    class BackgroundTask extends AsyncTask<Integer, Integer, Integer> {
        @Override
        protected void onPreExecute() {
            value = 0;
            progressBar.setProgress(value);
        }

        @Override
        protected Integer doInBackground(Integer... integers) {
            while(isCancelled() == false) {
                value++;
                if (value >= 100) {
                    break;
                } else {
                    publishProgress(value);
                }

                try{
                    Thread.sleep(1000);
                } catch(Exception e) {

                }

                return value;
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            progressBar.setProgress(values[0].intValue());
        }

        @Override
        protected void onPostExecute(Integer integer) {
            progressBar.setProgress(0);
        }

        @Override
        protected void onCancelled() {
            progressBar.setProgress(0);
        }
    }
}
Comments