android thread handler 설명

|

핸들러가 필요한이유는 다음과 같습니다.


안드로이드쓰레드는 특징이 하나 있습니다. 앞에서 쓰레드는 독립적인 스택공간을 가지지만 독립적인 전역 메모리 공간은 가지지못한다고했습니다.

그러면 지역변수들은 서로 분리가 되지만 쓰레드를 호출했던쪽의 쓰레드와 현재쓰레드는 같은 프로세스의 전역 메모리공간을 공유하게 됩니다. 그런데 서로 다른 쓰레드가 같은 전역 메모리를 접근할경우 임계영역 관련 이슈들이 나오게 됩니다. 그래서 안드로이드는 사전에 임계영역 관련 이슈를 원천차단하고자 쓰레드가 다르면 전역 메모리공간을 공유하지못하도록 했습니다. 다시 말해서 쓰레드객체의 멤버변수들은 다른 쓰레드에서 접근할수가없습니다.

다른쓰레드의 멤버에 접근해야할필요가 있으면 Handler를 통해서만 접근가능하도록 했습니다.



안드로이드에서 화면상에 버튼이나 텍스트박스등의 객체들의 인스턴스는 모두 ui 쓰레드에 있습니다.

따라서 위에서 설명한봐와같이 다른 thread 객체의 run함수 내에서는 ui쓰레드에 있는 객체들을 접근할수는 없습니다.

그래서 핸들러를 이용해서 우회적인 방법을 사용합니다.


public class MyHandler extends Handler {

        @Override

        public void handleMessage(Message msg) {


            Log.d(TAG,"handler call");


            mTextvw.append((String) msg.obj);

            mTextvw.append("\n");

        }

    }


핸들러는 위와 같이 정의 합니다.

Handler 에서 상속받고 handleMessage를 오버라이딩합니다. 그리고 핸들러 내부함수(handleMessage )에서는 ui쓰레드쪽 객체들을 사용할수 있습니다.

sendMessage 함수가 호출되면 handleMessage가 콜백 됩니다.


그리고 이것을 쓰레드나 러너블에서 상속 받은 클래스의 run 함수에서 sendMessage 함수를 호출해주면됩니다.

public void run() {     try {         Log.d(TAG,"1");         while (!Thread.currentThread().isInterrupted()) {             sleep(1000);             mHandler.sendMessage(mHandler.obtainMessage(1,0,0,"tick: " + System.currentTimeMillis()));             Log.d(TAG,"tick: " + System.currentTimeMillis());         }     } catch (InterruptedException e) {         e.printStackTrace();         Log.e(TAG,"InterruptedException");     } }


obtainMessage 함수로 메씨지 객체를 만들어서 넘겨줍니다.

이렇게 만들어진 객체는 handleMessage에서 Message 객체로 넘어오는 인자에 담겨지게됩니다.


obtainMessage 에 순서대로 what,arg1,arg2,obj 순서로 인자를 넘겨줍니다. 

받는쪽에서도 마찬가지로 what,arg1,arg2,obj 이름의 멤버변수로 넘겨운 인자들을 받아볼수있습니다.




MyActivity.java
package com.gbox3d.threadsample2; 
 
import android.app.Activity; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.util.Log; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.view.View; 
import android.widget.TextView; 
 
 
public class MyActivity extends Activity { 
 
    public TextView mTextvw; 
 
    public Handler mHandler; 
    public Thread mThread; 
 
    private final String TAG = "Thread_sample2"; 
 
 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_my); 
 
        mTextvw = (TextView) findViewById(R.id.textvw); 
        mHandler = new MyHandler(); 
 
 
 
        findViewById(R.id.button1).setOnClickListener( 
                new View.OnClickListener() { 
                    @Override 
                    public void onClick(View view) { 
                        if(mThread != null) { 
 
                            mThread.interrupt(); 
                            mThread = null; 
 
                        } 
                        else { 
                            mThread = new Thread() { 
                                @Override 
                                public void run() { 
                                    super.run(); 
 
                                    Log.d(TAG,"start"); 
 
                                    try { 
                                        Log.d(TAG,"1"); 
 
 
                                        while (!Thread.currentThread().isInterrupted()) { 
 
                                            sleep(1000); 
 
                                            mHandler.sendMessage(mHandler.obtainMessage(1,0,0,"tick: " + System.currentTimeMillis())); 
                                            Log.d(TAG,"tick: " + System.currentTimeMillis()); 
 
                                        } 
 
                                    } catch (InterruptedException e) { 
                                        e.printStackTrace(); 
                                        Log.e(TAG,"InterruptedException"); 
                                    } 
                                } 
                            }; 
                            mThread.start(); 
 
                        } 
 
                    } 
                } 
        ); 
        //findViewById() 
 
 
    } 
 
    @Override 
    protected void onDestroy() { 
        super.onDestroy(); 
 
        mThread.interrupt(); 
 
        Log.d(TAG,"ondestroy"); 
    } 
 
 
    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
        // Inflate the menu; this adds items to the action bar if it is present. 
        getMenuInflater().inflate(R.menu.my, menu); 
        return true; 
    } 
 
    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
        // Handle action bar item clicks here. The action bar will 
        // automatically handle clicks on the Home/Up button, so long 
        // as you specify a parent activity in AndroidManifest.xml. 
        int id = item.getItemId(); 
        if (id == R.id.action_settings) { 
            return true; 
        } 
        return super.onOptionsItemSelected(item); 
    } 
 
    public class MyHandler extends Handler { 
        @Override 
        public void handleMessage(Message msg) { 
 
            Log.d(TAG,"handler call"); 
 
            mTextvw.append((String) msg.obj); 
            mTextvw.append("\n"); 
        } 
    } 
 
 
 
 
} 


And