< 참고 블로그 링크 >
안드로이드는 기본적으로 메인 Thread를 실행하기 때문에 하나의 작업만 실행되기 때문에 이를 해결하기 위해 AsynTask
구문을 사용합니다.
메서드 | 설 명 |
---|---|
onPreExecute() | 백그라운드 실행 이전 초기화 메서드 |
doInBackground() | 백그라운드에서 돌아갈 동작을 구현 |
onProgressUpdate() | 실시간 작업 진행 상황을 확인하는 메서드 |
onPostExecute() | doInBackground() 를 종료하고 결과를 반환하는 메서드 |
onCancelled() | 작업이 취소되었을 때 실행되는 메서드 |
public class NetworkTask extends AsyncTask<Params, Progress, Result> {...}
Params : doInBackground()의 파라미터로 사용. execute(Params) 함수를 호출하면서 넘기는 파라미터
Progress : onProgressUpdate() 의 파라미터로 사용
Result : onPostExecute() 함수의 파라미터로 사용. doInBackground() 의 반환값
<?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>
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("종 료"); } } }
btnStart
의 setOnClickListener()
의 코드를
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초 동안 멈춰 있을 것이며 그 동안은
토스트 메시지를 실행할 수 없게 된다.