post list

2015년 8월 13일

[Android] Thread

DDMS 에서 원하는 앱을 선택하고 왼쪽고 상단에 화살표 세개 모양의 아이콘을 눌리고 오른쪽 창에서 같은 아이콘 모양의 Threads를 눌리면 현재 앱의 Thread 상태들을 볼 수 있다.

Android는 다음의 방식으로 Thread를 지원한다.

1. Looper
- 메시지 큐를 생성하고 초기화
- 메시지 큐에서 데이터를 꺼내서 Handler에게 전달

2. Handler
- Looper가 전달해 준 데이터를 처리
- 메시지 큐에 데이터를 삽입


UI Main Thread 도 Looper를 가지고 있으나 우리의 코드에 보이지는 않는다. 다만 Handler를 붙여서 Looper를 이용할 수는 있다.

보통 UI Thread와 다른 Thread (이하 Worker Thread) 간의 통신을 위해서 Handler를 사용하게 되는데 양방향 통신을 위해서는 Handler 또한 양 쪽 Thread 모두에게 붙여야 한다. Handler는 UI Thread와 Worker Thread에서 모두 접근 가능하도록 코드를 작성 해야 한다.

예제는 다음과 같다.

public class C16_Handler extends Activity {

int mMainValue = 0;
int mBackValue = 0;
TextView mMainText;
TextView mBackText;

@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.c16_thread);

mMainText = (TextView) findViewById(R.id.mainvalue);
mBackText = (TextView) findViewById(R.id.backvalue);

BackThread thread = new BackThread();
thread.setDaemon(true);
thread.start();
}

public void mOnClick(View v) {
mMainValue++;
mMainText.setText("MainValue : " + mMainValue);
}

class BackThread extends Thread {

@Override public void run() {
while (true) {
mBackValue++;
// mHandler.sendEmptyMessage(0);
Message msg = new Message();
msg.what = 0;
msg.arg1 = 0;
msg.arg2 = 0;
msg.obj = null;
mHandler.sendMessage(msg);

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

Handler mHandler = new Handler() {

@Override public void handleMessage(Message msg) {
if (msg.what == 0) {
mBackText.setText("BackValue : " + mBackValue);
}
}
};
}


Message를 다루는 방법도 여러가지가 있는데 여기서는 다루지 않겠다. 다만 다음과 같이 Pool 방식도 있음을 알아두자.

Message msg = Message.obtain();


다음은 명시적으로 Looper를 이용하는 방식의 예제다.


public class C16_Looper extends Activity {

int mMainValue = 0;

TextView mMainText;
TextView mBackText;
EditText mNumEdit;

CalcThread mThread;

@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.c16_looper);

mMainText = (TextView) findViewById(R.id.mainvalue);
mBackText = (TextView) findViewById(R.id.backvalue);
mNumEdit = (EditText) findViewById(R.id.number);

mThread = new CalcThread(mHandler);
mThread.setDaemon(true);
mThread.start();
}

public void mOnClick(View v) {
Message msg;

switch (v.getId()) {
case R.id.increase:
mMainValue++;
mMainText.setText("MainValue : " + mMainValue);
break;
case R.id.square:
msg = new Message();
msg.what = 0;
msg.arg1 = Integer.parseInt(mNumEdit.getText().toString());
mThread.mBackHandler.sendMessage(msg);
break;
case R.id.root:
msg = new Message();
msg.what = 1;
msg.arg1 = Integer.parseInt(mNumEdit.getText().toString());
mThread.mBackHandler.sendMessage(msg);
break;
}
}

Handler mHandler = new Handler() {

@Override public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
mBackText.setText("Square Result : " + msg.arg1);
break;
case 1:
mBackText.setText("Root Result : " + ((Double) msg.obj).doubleValue());
break;
}
}
};
}

class CalcThread extends Thread {

Handler mMainHandler;
Handler mBackHandler;

CalcThread(Handler handler) {
mMainHandler = handler;
}

@Override public void run() {
Looper.prepare();

mBackHandler = new Handler() {

@Override public void handleMessage(Message msg) {
Message retmsg = new Message();
switch (msg.what) {
case 0:
try {
Thread.sleep(200);
}
catch (InterruptedException e) {
;
}
retmsg.what = 0;
retmsg.arg1 = msg.arg1 * msg.arg1;
break;
case 1:
try {
Thread.sleep(200);
}
catch (InterruptedException e) {
;
}
retmsg.what = 1;
retmsg.obj = new Double(Math.sqrt(msg.arg1));
break;
}
mMainHandler.sendMessage(retmsg);
}
};

Looper.loop();
}
}






댓글 없음:

댓글 쓰기