ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 안드로이드 핸들러
    안드로이드 2020. 5. 9. 20:52
    728x90

    2020/05/09 - [Android & Kotlin] - 안드로이드 Looper, Message Queue

    2020/05/09 - [Android & Kotlin] - 안드로이드 스레드

    2020/05/09 - [Android & Kotlin] - 안드로이드 멀티스레드

     

    이전 글들을 통해서 메인스레드에서 할 수 없는 일을 알아봤으니 이번에는 메인스레드만 할 수 있는 일에 대해 알아볼게요

    안드로이드 단일 스레드 GUI 모델

    안드로이드는 화면을 갱신하는 작업을 반드시 메인 스레드에서만 하도록 되어 있어요.

    화면이라는 것도 굉장히 중요한 자원 중 하나에요

    이런 자원에 대해서 여러 스레드가 동시에 접근하게 된다면 버튼을 그리다가 표를 그리고.. 그러다가 이미지를 그리고.. 그러면 자원 자체가 꼬이기 쉬워요. 그래서 안드로이드 뿐만 아니라 대부분의 GUI 디바이스들은 메인 스레드에서만 화면갱신을 가능하게 하도록 한답니다.

     

    서브 스레드에서 화면 갱신을 할 때 어떤 문제가 생기는지 알아볼게요

     

    <layout/activity_main.xml>

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
    
        <Button
            android:id="@+id/btn"
            android:text="버튼"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    
    </LinearLayout>

    <MainActivity.java>

    package kr.co.sample;
    
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    public class MainActivity extends AppCompatActivity {
        Button btn;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            btn = findViewById(R.id.btn);
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for (int i = 0; i < 10; i++) {
                                btn.setText(String.valueOf(i));
                                try {
                                    Thread.sleep(1000);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }).start();
    
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for (int i = 10; i < 20; i++) {
                                btn.setText(String.valueOf(i));
                                try {
                                    Thread.sleep(1000);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }).start();
                }
            });
        }
    }
    

    결과

    Only the original thread that created a view hierachy can touch its views.

    뷰를 만든 스레드만이 뷰를 건드릴 수 있다고합니다. 뷰를 만든 스레드가 메인 스레드( = ui 스레드) 입니다.

     

    Handler

    작업 스레드에서 뷰 작업을 하려면 Handler 객체를 이용해야 합니다.

    메인스레드에게 "나 작업스레든데 너가 뷰를 이렇게 바꿔줬으면 좋겠어~" 라고 부탁하는 통신 수단이 Handler 입니다.

     

    <MainActivity.java>

    new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                final int I = i;
                
                // post 의 run 은 메인스레드가 실행시켜줌
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        btn.setText(String.valueOf(I));
                    }
                });
    
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }).start();
    
    new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 10; i < 20; i++) {
                final int I = i;
                
                // post 의 run 은 메인스레드가 실행시켜줌
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        btn.setText(String.valueOf(I));
                    }
                });
    
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }).start();

     

     

    핸들러를 통해서 실행시키면 post 의 run 메소드는 메인 스레드가 실행시켜주기 때문에 에러가 발생하지 않습니다.

     

     

    2020/05/09 - [Android & Kotlin] - 안드로이드 Looper, Message Queue

     

    안드로이드 Looper, Message Queue

    안드로이드 멀티스레드 프로그래밍에 대해 제대로 이해하려면 Looper 에 대해서 제대로 이해하고 있어야해요 구조 메인스레드 내부적으로 Looper 객체가 있습니다. Looper 는 무한 루프를 돈다고하��

    bubble-dev.tistory.com

     

    '안드로이드' 카테고리의 다른 글

    안드로이드 CountDownTimer  (0) 2020.05.13
    Android AsyncTask  (0) 2020.05.10
    안드로이드 Looper, Message Queue, Handler  (0) 2020.05.09
    안드로이드 멀티스레드  (0) 2020.05.09
    안드로이드 스레드  (0) 2020.05.09

    댓글

Designed by Tistory.