76일차(4)/Android App(36) : AsyncTask
- 새 모듈 생성- step16asynctask
- AsyncTask : 비동기작업
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"
tools:context=".MainActivity"
android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="무언가 입력해 보세요..."/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/sendBtn"
android:text="전송"/>
</LinearLayout>
Messenger 클래스생성
package com.example.step16asynctask;
import android.util.Log;
public class Messenger {
//가상으로 메세지를 보내는 static 메소드
public static void sendMessage(String msg){
Log.e("Messenger sendMessage()", "메세지 전송중...");
//메세지를 전송하는 데 20초가 걸린다고 가정
try{
Thread.sleep(20000);
}catch (InterruptedException e){
e.printStackTrace();
}Log.e("Messenger sendMessage()", "메세지 전송 완료");
}
}
- 메신저의 static 메소드를 수행하면서 어떤 작업을 하려고 한다.
- 어떤 메시지를 전송하는 데 20초가 걸린다고 가정하기!
- 여기에 실행순서가 들어올 때, 20초 동안 메인스레드에 실행 순서가 잡혀 있는 것이 문제이다.
MainActivity
package com.example.step16asynctask;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.Button;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//전송버튼
Button sendBtn=findViewById(R.id.sendBtn);
sendBtn.setOnClickListener(v -> {
/*
시간이 오래 걸리거나 혹은 실행 시간이 불확실한 작업은
Main thread(UI thread) 에서 하면 안 된다.
*/
//비동기 task 객체를 생성해서
SendTask task=new SendTask();
//execute() 메소드를 호출해서 작업을 시작한다.
task.execute("hello", "...", "bye!");
});
}
/*
비동기 작업을 도와줄 클래스 설계하기
1. AsyncTask 추상 클래스를 상속받는다.
2. AsyncTask<파라미터 type, 진행중 type, 결과 type> 에 맞게끔
Generic 클래스를 잘 정의한다.
3. doInBackground() 메소드를 오버라이드한다.
4. 추가로 필요한 메소드가 있으면 추가로 오버라이드한다.
*/
public class SendTask extends AsyncTask<String, Void, Void>{
//백그라운드에서 작업할 내용을 여기서 해준다(새로운 스레드에서 할 작업)
@Override
protected Void doInBackground(String... strings) {
//여기는 UI 스레드가 아니다!! 즉 UI를 업데이트할 수 없다.
//String... 은 String[] 로 간주해서 사용하면 된다.
Messenger.sendMessage(strings[0]);
//작업에 결과가 있다면 return 해주면 되고
return null;
}
// doInBackground() 메소드가 리턴하면 자동으로 호출되는 메소드
@Override
protected void onPostExecute(Void unused) {
super.onPostExecute(unused);
//여기는 UI 스레드이기 때문에 UI에 관련된 작업을 마음대로 할 수 있다.
new AlertDialog.Builder(MainActivity.this)
.setMessage("작업성공")
.create()
.show();
}
}
}
- 전송 버튼을 누르면 20초간 앱이 멈춘다. 더이상 입력도 할 수 없다. 응답하지 않는다.
- 사용자의 요청에 응답하지 않으면 운영체제가 알아차리고 강제종료시킬 수가 있다.
- 이렇게 시간이 오래 걸리거나 혹은 실행 시간이 불확실한 작업은
Main thread(UI thread) 에서 하면 안 된다.
- 아래에 새 클래스 생성. AsyncTask 상속
- 3개의 제너릭 타입을 지정
public class SendTask extends AsyncTask<String, Void, Void>{
}
- 이렇게 작성해준 후 메소드 오버라이드
- 3개의 제너릭<> 은 각각 파라미터 타입, 진행중 타입, 결과 타입인데
따로 작업의 결과가 없으면 그냥 Void 라고 한다.
Messenger.sendMessage("")
- 위쪽 스레드가 아니라 백그라운드 메소드에서 이 작업을 한다.
- 이 SendTask 클래스를 사용하는 방법은? onCreate() 메소드 안에서 객체를 생성해서 execute() 에 넣어준다
- 받는 파라미터가 동적이다.(여러개의 인자가 들어갈 수 있다)
- execute() 에 들어간 인자가 여기에 담긴다.
- String... 은 String[ ] 배열이라고 생각하고 사용하면 된다!
- 받아서 인덱스의 방 번호로 호출한다.
- run 해보면 이제 메시지가 전송되고 있어도 정지되지 않는다.
- 전송을 보내고 20초 기다리면 작업 성공이라는 알림이 뜬다!
- AsyncTask는 현재 deprecated 되어있다.
- 즉 장기적으로 사용을 하지 않을 예정이다. 하지만 아직 동작은 한다.
- 비동기작업. 백그라운드에서 사용되는 doInBackground 메소드는 기존과는 다른 별개의, 새로운 스레드이다.
- 작업에 필요한 파라미터들은 여기에 담긴다.
- 파라미터 타입이 String인 이유, 진행,결과 타입이 void인 이유는 인자를 그 타입으로 받기 때문이다.
- 여기는 UI 스레드가 아니다!! 즉 UI를 업데이트할 수 없다.
- list에 결과를 출력하는 등의 동작은 이 스레드에서는 할 수 없다.
- onPostExecute() 메소드에서 따로 UI 업데이트를 할 수 있다.
- 시간이 많이걸리는 동작은 별도의 스레드에서!
- 작업이 끝나면 자동으로 onPostExecute 로 리턴된 것이 전달된다.(여기서는 void)
- 작업의 결과물을 가지고 UI를 업데이트할 수 있다.
- 파라미터, 과정, 결과 타입 알아두기!
- 작업이 끝났을때 알림을 띄우도록 onPostExecute에 이어질 작업 코딩
'국비교육(22-23)' 카테고리의 다른 글
77일차(2)/Android App(38) : Http POST방식 요청하기(1) (0) | 2023.01.27 |
---|---|
77일차(1)/Android App(37) : AsyncTask(2) (0) | 2023.01.27 |
76일차(3)/Android App(35) : WebView (1) | 2023.01.26 |
76일차(2)/Android App(34) : SQLite 활용(2) (0) | 2023.01.26 |
76일차(1)/Android App(33) : SQLite 활용(1) (0) | 2023.01.26 |