안녕하세요 ! 초보개발자 입니다.
이 블로그는 개인 공부 정리용 블로그 입니다.
혹 잘못된 내용이 있다면 지적 부탁드리겠습니다.
그리고 질문주신다면 최대한 아는선에서 답변드리도록 하겠습니다.
그럼 시작하도록 하겠습니다.
핸들러(Handler)
저번 강의에서 쓰레드를 이용하여 1초마다 값이 증가하는 코드를 작성 하였습니다. 1초마다 증가하는 값을 주기 위해 쓰레드를 사용하였는데 버튼을 클릭 할 경우에만 값을 확인 할 수 있었습니다. 저번시간에 썼던 코드를 보시면 아래와 같습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | package com.example.donghyun.thread; import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity { int value; Button button =null; TextView textView = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button =(Button)findViewById(R.id.button); textView =(TextView)findViewById(R.id.aa); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { textView.setText("value 값 :"+value); } }); Thread t = new Thread(new Runnable() { @Override public void run() { while(true){ value++; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }); t.start(); } } | cs |
버튼 클릭 없이 실시간으로 값을 보기 위한 방법은 무엇일까요 ? 아래코드와 같이 textView.setText("value 값: "+value); 스레드 내부에 넣으면 될 거 같습니다. 하지만 아래와 같이 코딩후 실행을 하면 다음과 같은 에러가 발생하게 됩니다.
Only the original thread that created a view hierarchy can touch its views.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Thread t = new Thread(new Runnable() { @Override public void run() { while(true){ value++; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } textView.setText("value 값 :"+value); } } | cs |
위의 영어를 해석하면 오리지널 스레드에서만 UI를 변경한다는 뜻으로 해석할 수 있습니다. 즉 UI를 변경하는 코드는 main 스레드에서만 사용할 수 있습니다. 이게 안드로이드 룰입니다. 그래서 이러한 문제를 해결하기 위한 방법중 하나가 핸들러를 이용 하는 것입니다. 핸들러를 이용하여 위의 코드를 고쳐 보겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | package com.example.donghyun.thread; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends AppCompatActivity { int value; Button button =null; TextView textView = null; Handler handler =null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button =(Button)findViewById(R.id.button); textView =(TextView)findViewById(R.id.aa); handler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case 1: textView.setText("value 값 :"+value); break; } super.handleMessage(msg); } }; Thread t = new Thread(new Runnable() { @Override public void run() { while(true){ value++; try { Thread.sleep(1000); Message msg = handler.obtainMessage(1,value); handler.sendMessage(msg); } catch (InterruptedException e) { e.printStackTrace(); } } } }); t.start(); } } |
위의 코드를 분석하여 보겠습니다.
1. UI를 변경할 수 있게 액티비티 클래스내부에 핸들러를 구현합니다.
2. 핸들러 클래스의 handlerMessage 메소드를 정의 합니다. 이 메소드는 스레드로 부터 받은 메시지를 처리합니다. 메시지를 구별하기 위해 switch문을 사용 합니다.
3. 스레드에서 핸들러로 메시지를 전달하기 위해 스레드 내부에 Message 객체를 생성합니다. new 연산자를 이용하여 생성하는 것 보다 handler의 obtainMessage 메소드를 이용합시다.
obtainMessage의 타입은 다음과 같이 5가지 입니다.
● obtainMessage()
● obtainMessage(int what)
● obtainMessage(int what,Object obj)
● obtainMessage(int what,int arg1,int arg2)
● obtainMessage(int what,int arg1,int arg2,Object obj)
파라메터는 다음과 같습니다.
int what - 메세지의 종류를 구별하기 위해 사용됩니다.
int arg1 - 정수 데이터를 전달할 때 사용 됩니다.
int arg2 - 정수 데이터를 전달할 때 사용 됩니다.
Object obj - 객체를 전달 할 때 사용 됩니다.
4. sendMessage 메소드를 통해 msg를 핸들러로 전달 합니다.
위 내용을 바탕으로 코드를 분석해보시면 될 거 같습니다.
이상으로 핸들러에 대해서 알아보았습니다.
'프로그래밍 > 안드로이드' 카테고리의 다른 글
[안드로이드] 데이터베이스(sqlite) 사용법 (25) | 2017.05.29 |
---|---|
[안드로이드] 스레드(Thread) (0) | 2017.05.19 |
[안드로이드] 프로그래스바(ProgressBar) 사용하기 (2) | 2017.05.18 |
[안드로이드] 리스트 뷰(ListView) 이용하기 (0) | 2017.05.17 |
[안드로이드] 스피너(Spinner) 이용하기 (1) | 2017.05.16 |