안드로이드 handler, AsyncThread 사용하기
Handler
안드로이드의 UI는 메인 스레드에서만 변경할 수 있습니다.
그래서 만약 서브 스레드에서 UI를 변경하고 싶으면 Handler를 사용해야합니다.
즉, 서브 스레드 -> Handler -> 메인 스레드 과정을 거쳐서 서브 스레드에서 UI를 변경할 수 있습니다.
아래 예제는 서브 스레드에서 TextView의 글자를 바꾸는 예제입니다.
Handler를 생성하는 스레드만 다른 스레드가 보내는 Message 객체나 Runnable 객체를 받을 수 있으므로
메인 스레드에서 Handler를 생성해 줘야합니다.
public class MainActivity extends AppCompatActivity {
TextView tv;
int i;
Handler mhandler = new Handler(){
@Override
public void handleMessage(Message msg) {
tv.setText("숫자 : "+ i);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView)findViewById(R.id.text1);
}
public void onClick(View v){
SubThread th = new SubThread();
th.start();
}
class SubThread extends Thread{
@Override
public void run() {
for(i = 1; i <= 10; i++){
try {
Thread.sleep(1000);
Message msg = mhandler.obtainMessage();
mhandler.sendMessage(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Handler를 이용해서 로딩화면을 구현해 줄 수 있습니다.
Handler의 postDelayed는 첫 번째 인자로 Runnable 객체, 두 번째 인자로 입력된 시간 후에 Runnable객체가 실행되게 합니다.
아래 예제에서는 3초후에 화면이 바뀌도록 설정한 예제입니다.
public class LoadingActivity extends AppCompatActivity {
Handler mhandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_loading);
mhandler = new Handler();
mhandler.postDelayed(new Runnable() {
@Override
public void run() {
Intent i = new Intent(LoadingActivity.this, MainActivity.class);
startActivity(i);
finish();
}
}, 3000);
}
}
AsyncTask
AsyncTask는 Handler를 사용하지 않고 UI 처리를 할 수 있고, Background 작업을 할 수 있습니다.
AsyncTask에는 5개의 Override 메소드가 있습니다.
- onPreExecute() - AsyncTask가 실행될 때 처음 실행되는 메소드로 UI 변경을 할 수 있습니다.
- doInBackground(Params...) - 백그라운드 스레드에서 처리되는 메소드 입니다. 진행 중 UI작업이 필요한 경우 publish Progress함수를 호출하면 UI 작업을 하는 onProgressUpdate가 호출됩니다.
- onProgressUpdate - doInBackground에서 publishProgress를 호출하면 실행되는 메소드로 UI를 변경할 수 있습니다.
- onPostExecute(Result) - doInBackGround 메소드 종료 후 호출되고 doInBackGround의 리턴 값을 받습니다.
- onCancelled() - doInBackground 메소드에서 작업이 호출되면 onPostExecute 대신 호출됩니다.
생성법은 아래와 같습니다.
AsyncTask<String, Integer, Long>
- String - doInBackground 메소드의 전달 값
- Integer - onProgressUpdate 메소드의 전달 값
- Void - doInBackground의 반환 값
class myTask extends AsyncTask<String,Integer,Void>{
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Long doInBackground(String... params) {
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
@Override
protected void onCancelled() {
super.onCancelled();
}
}
생성한 AsyncTask를 실행하고 싶을 때는 .execute() 종료하고 싶을 때는 .cancel(true)를 생성합니다.
.execute에 넣어준 인자는 doInBackground에서 사용할 수 있습니다.
myTask task = new myTask();
task.execute(0);
task.cancel(true);
아래 예제는 Handler와 AsyncTask를 사용한 예제입니다.
코드는 깃 허브에서 볼 수 있습니다.
https://github.com/Ywook/AndroidPractice11
![](https://t1.daumcdn.net/cfile/tistory/216DA347592D0A3206)