프로그래밍/안드로이드

안드로이드 루퍼(looper)!? 쓰레드와 관포지교 관계

가카리 2012. 8. 22. 20:45
반응형

루퍼(looper)

 

지금까지 쓰레드끼리 Message객체를 만들어서 정보를 주고 받는다고 생각하면 잘못된 것입니다. 예제들을 보면 메인쓰레드만 Message객체를 받고 있음을 알 수 있습니다.

 

즉 메인쓰레드는 루퍼란 것을 가지고 있기때문에 메시지를 받을 수 있었습니다.

 

루퍼란놈은 메시지큐에서 메시지를 꺼내서 핸들러에 보내는 역할을 합니다(이전 소스보면 메인쓰레드 안에 Handler mHanler = new Handler()를 했음을 알 수 있습니다.

 

그렇다면 서브쓰레드에도 메시지를 받을 수 있게 할려면?

 

서브쓰레드에도 루퍼를 만들어주면 됩니다.

 

static void prepare() : 현재 쓰레드를 위한 루퍼를 준비합니다

static void loop() 큐에서 메시지를 꺼내 핸들러로 전달하는 루프를 실행합니다(일종의 start)

void quit() 루프를 종료합니다.(루퍼를 없앤다는 얘기)

 

다음은 루퍼를 구하는 메소드입니다.

 

Thread getThread() 루퍼와 연결된 쓰레드를 구합니다.

static Looper getMainLooper() 메인쓰레드의 루퍼를 구합니다.

static Looper myLooper() 현재쓰레드의 루퍼를 구합니다. 없으면 null반환

 

주석 열심히 달아놨습니다. 읽어봐서 이해안되시면 댓글달아주세요. 제가 이해 못한거니까요.

 

main.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

> 

<TextView

       android:id="@+id/mainvalue"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="MainValue : 0"

/>

<Button

       android:id="@+id/increase"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:onClick="mOnClick"

android:text="Increase"

/>

<EditText

       android:id="@+id/number"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:numeric="integer"

android:text="5"

/>

<TextView

       android:id="@+id/backvalue"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="BackValue : 0"

/>

<Button

       android:id="@+id/square"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:onClick="mOnClick"

android:text="Square"

/>

<Button

       android:id="@+id/root"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:onClick="mOnClick"

android:text="Root"

/>

</LinearLayout>

 

 

 

자바파일

 

package com.android.ex93;

 

import android.app.*;

import android.os.*;

import android.view.*;

import android.widget.*;

 

public class ex93 extends Activity {

       int mMainValue = 0;

       TextView mMainText;

       TextView mBackText;

       EditText mNumEdit;

       CalcThread mThread;

 

       public void onCreate(Bundle savedInstanceState) {

             super.onCreate(savedInstanceState);

             setContentView(R.layout.main);

 

             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() {

             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;

       }

 

       public void run() {

             Looper.prepare();//루퍼만들기~

             mBackHandler = new Handler() {//메인쓰레드가 보낸 메시지를 여기서 받음

                    //물론 받기 이전에 루퍼를 만들어줘야됨

                    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((double)msg.arg1));//받은 메시지를 처리하는 부분

                                 break;

                           }

                           //받은 메시지를 가공한뒤에 다시 메인쓰레드한테 보냄

                           //여기서는 메시지 큐까지 보내게됨

                           mMainHandler.sendMessage(retmsg);

                    }

             };

             //메시지큐에 있는 내용을 실제 핸들러한테 보냄!

             //서브쓰레드 -> 메시지큐-> 메인쓰레드 핸들러 이렇게

             Looper.loop();

       }

}