티스토리 뷰

Thread를 사용하면


자동적으로 화면을 바꿔지도록 만들 수가 있습니다.


다만 Thread상에서는 화면의 UI를 바꿀 수가 없는데 이를 해결해주는 것이 Handler입니다.




어플을 실행하면

핸드폰(디바이스) 내의 메모리(RAM)에 해당 어플리케이션 실행영역이 할당되는데 하나의 프로그램이 작동하는 것을 하나의 프로세스다 라고 말합니다. 하나의 프로그램(프로세스)안에서도 내부 프로세스를 만들 수가 있습니다. 프로세스 실행과 동시에 메인스레드가 실행되는 것이고, 추가적으로 만드는 내부 프로세스가 우리가 공부하는 Thread(스레드)입니다. 자바언어는 멀티스레드를 가질 수 있는 특징이 있어서 안드로이드에서도 스레드를 만들어서 내부적으로 여러 기능을 추가할 수 있다는것을 알아두시면 되겠습니다.


꼭 알아둬야 하는 부분은 서버를 열고닫고 연결하는 통신을 메인스레드에서 실행시키면 프로세스가 엉켜버릴 수 있어서 에러가 나버립니다. 꼭 스레드를 새로 만들어서 돌리면 되겠습니다.





또 스레드의 큰 특징은 스레드는 백그라운드내에서 돌아가는 것이기 때문에 직접적으로 UI 수정이 불가능합니다.

이 떄 UI를 수정할 수 있게 하는 방법은 여러가지가 있는데 자세한건 코드를 보면서 사용법을 숙지하시면 되겠고, 개념적으로 Handler에 대해서 알아 두시면 되겠습니다. Thread에서 Message를 생성하고 이 Message를 Handler로 전송하면 Handler에서 명령을 받아 UI를 변경할 수 있게 할수 있습니다. 간혹가다가 스레드안에서 그냥 UI변경하는 메소드를 넣으시는 분이 있는데 그러면 에러가 나버립니다.

(키워드만 진하게 했는데 바쁘시면 저거만 보고 넘어가시면 됩니다.)


Handler는  손잡이라는 의미죠? UI를 변경하는것도 자동차를 타면서 핸들돌리듯이 내가 마음껏 바꿀 수 있게 해주는 것입니다. 


Thread와 비슷한 AsyncTask는 다음 포스팅에서 확인해주세요



<Thread 사용하기>

 쓰레드를 상속받아서 MyTHread 받기

/**
* JAVA는 프로그램안에서 작은 프로그램을 만들 수 있는 멀티쓰레드를 지원한다
* (특징이니 알아두도록하자)
* Thread에서 사용하는 메소드는 run이다.
* Thread는 프로그램의 Back에서 돌아가기 때문에 UI변경이 불가능하다.
* 그래서 여러가지 방법이 있다.
* 1. Handler.sendMessage 사용
* 2. Handler.post 사용
* 3. runOnUiHandler 사용
*/
class MyThread extends Thread{
@Override// run을 오버라이딩
public void run() {
/* 이곳에 반복적으로 적용하고 싶은 내용을 적는다.
* 예시로 알아보기 쉽도록 반복문으로 작성했다.
*/
int cnt = 0; // 1초에 1씩 증가하는 변수 선언


첫번째 UI변경 방법 Handler.sendMessage

Message 클래스의 구조를 찾아보는건 숙제입니다.

/**
* 1번 방법 Handler.sendMessage 이용
* 아래쪽에 Handler를 정의했고, Handler로 보낼 메시지를 만들어서 보내는 방법
* Message클래스의 구조를 잘 파악 해보자
* what : int 식별하는데에 쓰는 정수형 변수
* arg1, arg2 : int 인자 전달시에 사용하는 정수형 변수
* obj : Object 정보전달 시에 String으로 넘길수도 있도록 클래스자체로 전달이 가능한 변수
*/
Message uiMessage = uiHandler.obtainMessage();//Handler로 보낼 수 있는 메시지 만들기
// (새로 선언이 아니라 해당 핸들러에서 가져온다.)
while(cnt < 20){
cnt++;
if(cnt < 10) {
uiMessage.what = cnt % 3; // what의 값에 따라 다른 효과가 나도록 Handler에서 코딩한다.
uiMessage.obj = "sampleString"; // 어떤 객체든 넣을 수 있는데 String 객체를 넣어봤다.
uiMessage.arg1 = 1; // arg1, agr2 둘다 그냥 쓰는데, 단순 ui변경시엔 what만 사용한다.
uiMessage.arg2 = 2;
uiHandler.sendMessage(uiMessage); //Handler로 만든 메시지 보내기
}
SystemClock.sleep(1000); // 1초마다 작동하도록 sleep
}


/**
* Thread는 화면의 UI를 바꿀 수 없어서 Handler를 이용해서 UI를 변경한다.
* Message의 구조상 what을 식별자로 사용하여 경우에 따른 다른 UI변경을 구현할 수 있다.
*/
Handler uiHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what) {//what의 경우에 따라서 분류해서 사용
//예제에서는 3으로 나눈 나머지가 들어오기 때문에 0, 1, 2 로 구분해서 사용
case 0:
editText.setBackgroundColor(Color.GRAY);
break;
case 1:
editText.setBackgroundColor(Color.LTGRAY);
break;
case 2:
editText.setBackgroundColor(Color.MAGENTA);
break;
}
String s = editText.getText().toString() + "\n";
editText.setText(s);
}
};



 두번째 UI변경하는 방법 Handler.post 사용하기

쓰레드 화면에서 바로 생성해서 사용하는방법

/**
* 2번 방법 Handler.post 사용하기
* post 메소드에 들어가는 인자가 Runnable인데 Runnable을 오버라이딩하여 바꿀 수 있다.
*/
while(cnt < 40){
cnt++;
final int a = cnt; //익명함수에 쓸 때는 final로 선언해야하기 때문에 새롭게 선언
uiHandler.post(new Runnable() {
@Override
public void run() {
if(a == 25) editText.setBackgroundColor(Color.RED);
String s = editText.getText().toString() + "\n";
editText.setText(s);
}
});
SystemClock.sleep(1000); // 1초마다 작동하도록 sleep
}



세번째 UI변경하는 방법 runOnUiHandler 사용하기

2번과 마찬가지로 바로 바꾼다.

/**
* 3번 방법 runOnUiHandler사용하기
* 2번과 동일하게 Runnable을 오버라이딩해서 사용한다.
*/
while(cnt < 60){
cnt++;
final int a = cnt;
runOnUiThread(new Runnable() {
@Override
public void run() {
if(a == 45) editText.setBackgroundColor(Color.YELLOW);
String s = editText.getText().toString() + "\n";
editText.setText(s);
}
});
SystemClock.sleep(1000); // 1초마다 작동하도록 sleep
}


이 소스는 git에서도 확인이 가능합니다.

https://github.com/geusan/dco_android_thread_asynctask