[ 안드로이드 스튜디오 ] 비동기 - AsynTask에 대해 알아보자 (Java)

ma.caron_g·2022년 3월 12일
0
post-thumbnail

< 참고 블로그 링크 >

[ AsyncTask ]

안드로이드는 기본적으로 메인 Thread를 실행하기 때문에 하나의 작업만 실행되기 때문에 이를 해결하기 위해 AsynTask 구문을 사용합니다.

메서드설 명
onPreExecute()백그라운드 실행 이전 초기화 메서드
doInBackground()백그라운드에서 돌아갈 동작을 구현
onProgressUpdate()실시간 작업 진행 상황을 확인하는 메서드
onPostExecute()doInBackground()를 종료하고 결과를 반환하는 메서드
onCancelled()작업이 취소되었을 때 실행되는 메서드

[ AsyncTask Generic Type ]

public class NetworkTask extends AsyncTask<Params, Progress, Result> {...}
  • Params : doInBackground()의 파라미터로 사용. execute(Params) 함수를 호출하면서 넘기는 파라미터

  • Progress : onProgressUpdate() 의 파라미터로 사용

  • Result : onPostExecute() 함수의 파라미터로 사용. doInBackground() 의 반환값

[ 구현해보기 ]

[ activity_main .xml ]

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:layout_marginTop="200dp"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_margin="10dp">
        <ProgressBar
            android:id="@+id/prgBar"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:max="100"/>
        <TextView
            android:id="@+id/txtState"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="10dp"
            android:text="0%"
            android:textSize="18sp"
            android:textStyle="bold"/>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:layout_gravity="center">
            <Button
                android:id="@+id/btnStart"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="10dp"
                android:backgroundTint="#FF5656"
                android:text="실 행"
                android:textSize="18sp"
                android:textStyle="bold"
                android:textColor="#FFFFFF"/>
            <Button
                android:id="@+id/btnStop"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="10dp"
                android:backgroundTint="#FF5656"
                android:text="중 지"
                android:textSize="18sp"
                android:textStyle="bold"
                android:textColor="#FFFFFF"/>
        </LinearLayout>

    </LinearLayout>

</LinearLayout>

[ MainActivity.java ]

package com.study.asynctask;

import androidx.appcompat.app.AppCompatActivity;

import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    TextView txtState;
    ProgressBar prgBar;
    Button btnStart, btnStop;

    ProgressTask progressTask = null;

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

        txtState = findViewById(R.id.txtState);
        prgBar = findViewById(R.id.prgBar);

        btnStart = findViewById(R.id.btnStart);
        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                progressTask = new ProgressTask();
                progressTask.execute(100);
            }
        });

        btnStop = findViewById(R.id.btnStop);
        btnStop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                progressTask.cancel(true);
            }
        });
    }

    class ProgressTask extends AsyncTask<Integer, Integer, Integer> {
        int val;

        public void ProgressBar(int val) {
            this.val = val;
        }

        // 초기화 코드
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            val = 0;
            prgBar.setProgress(val);
        }

        // 백그라운드 작업 실행
        //  UI 작업 불가
        @Override
        protected Integer doInBackground(Integer... integers) {
            while(!isCancelled()) {
                val++;
                if(val >= 100) {
                    break;
                } else {
                    publishProgress(val);
                }
                try {
                    if(val<98) {
                        Thread.sleep(20);
                    }
                    else {
                        Thread.sleep(1000);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
            return val;
        }

        // Background 작업 중 UI 작업 진행
        // publishProgress() 통해 호출
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            prgBar.setProgress(val);
            txtState.setText("현재 " + val + " %");
        }

// 결과를 반환.
        @Override
        protected void onPostExecute(Integer integer) {
            super.onPostExecute(integer);

            txtState.setText("완 료");
        }

        // 취소 시 발생할 이벤트
        @Override
        protected void onCancelled() {
            super.onCancelled();

            txtState.setText("종 료");
        }
    }
}

[ 구현 ]

[ 작업이 돌아가고 있을 때 토스트 시켜보기 ]

[ 비동기 AsyncTask를 사용하지 않을 때 ]

btnStartsetOnClickListener()의 코드를

btnStart = findViewById(R.id.btnStart);
        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
//                progressTask = new ProgressTask();
//                progressTask.execute(100);
                int val = 0;
                while(val < 100){
                    val++;
                    prgBar.setProgress(val);
                    txtState.setText(val + " %");

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e){
                        e.printStackTrace();
                    }
                }
            }
        });

로 바꾸어주어보았다.

쓰레드가 sleep되면서 0.1 초 * 100(%) 10초 동안 멈춰 있을 것이며 그 동안은
토스트 메시지를 실행할 수 없게 된다.

profile
다른 사람이 만든 것을 소비하는 활동보다, 내가 생산적인 활동을 하는 시간이 더 많도록 생활화 하자.

0개의 댓글