Sam Story

핸들러 (Handler) 본문

Android

핸들러 (Handler)

Sam H 2024. 5. 13. 18:35

 

1. 핸들러(Handler) 란?

 

우선 핸들러에 대해알기 위해서는 스레드에 대한 이해가 필요하다. 

 

스레드에 대한 이해가 부족하다면 아래 포스팅을 참고하고 오도록 하자.

 

JAVA - 스레드 (Thread)

1. 스레드 (Thread) 란? 사전적 의미로는 '실' 이라는 뜻이다. 프로그래밍에 있어서 스레드는 프로그램 내에서 실행되는 흐름의 '단위' 라고 할 수있다. 모든 프로그램에는 최소 한개의 스레드가

samtistory.tistory.com

 

 

안드로이드의 UI 처리는 메인스레드 에서만 접근이 가능하다.

 

이러한 이유는 UI 동작의 무결성 즉

 

동시 다발적으로 어떠한 뷰에 상호작용을 하는것을 막기 위함이다.

 

 

그렇다면 통신을 이용해서 별도의 스레드로 데이터를 받아온 후 뷰를 초기화 하는 작업은 어떻게 처리 해야할까?

 

이에 대한 해결책은 다른 스레드에서 메인 스레드로 결과를 전송하는 방식이 이용된다.

 

즉 스레드간의 통신을 구현하는 것이다.

 

 

이러한 통신을 원활하게 할 수 있는것이 핸들러(Handler) 이다.

 

그렇기에 핸들러는 별도의 스레드에서 작성해 주어야 한다.

 

 

 

2. 예제

오늘의 예제는 코틀린이 아닌 자바로 작성한다.

 

그 이유는 코틀린에서는 핸들러가 Deprecated 되어서 그렇다.

 

그렇다면 핸들러에 대한 공부가 필요 없다고 생각 할 수도 있겠지만 메인 스레드가 아닌 별도의 스레드로

 

UI 를 갱신해주는 핸들러에 대한 이해가 없으면 이를 대체할 다른 기능에 대해서도 이해가 부족할거라 생각해

 

오늘 포스팅을 진행 하도록 하겠다.

 

 

오늘의 예제는 버튼을 누르면 1초마다 TextView의 값이 10번 갱신되는 예제로 진행해 보겠다.

 

 

메인 액티비티 레이아웃

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="0"
        android:textSize="40sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.3" />

    <Button
        android:id="@+id/button"
        android:text="시작"
        android:layout_marginHorizontal="20dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

 

메인 액티비티

package com.example.handlerexample;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import org.w3c.dom.Text;

public class MainActivity extends AppCompatActivity {

    TextView textView;
    Button button;

    Handler handler;

    // TextView 에 띄워줄 변수
    int count = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 뷰 초기화
        textView = (TextView) findViewById(R.id.textView);
        button = (Button) findViewById(R.id.button);

        // 핸들러 객체 초기화
        handler = new Handler();

        // 버튼 클릭 리스너
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // 버튼을 누를 때 마다 새로운 스레드 생성
                // 별도의 스레드 작성
                new Thread(){

                    @Override
                    public void run() {

                        for (int i = 0; i < 10; i++) {

                            try {

                                count ++;

                                // UI 를 지속적 으로 변경 해줘야 하기 때문에 handler 작성
                                handler.post(new Runnable() {
                                    @Override
                                    public void run() {

                                        textView.setText(""+count);

                                    }
                                });

                                // 1초 딜레이
                                Thread.sleep(1000);

                            } catch (InterruptedException e) {

                                throw new RuntimeException(e);

                            }

                        }


                    }

                }.start(); // Thread.start() 메서드 호출

            }
        });

    }
}

 

필요한 내용은 주석을 달아서 어느정도 설명은 해놨다.

 

 

실행 결과

실행 결과 값

 

위 코드로 만든 예제를 실행해보면 텍스트뷰의 값이 1씩 증가하는 걸 볼 수 있고

 

버튼을 누를 때마다 새로운 스레드가 생성되어 스레드가 중첩되서 한번에 숫자가 많이 올라가는 것도 볼 수있다.

 

 

이처럼 메인 스레드가 아닌 별도의 스레드로 UI를 갱신하려면 핸들러를 사용해야 오류가 나지않고

작성할 수 있다.

 

 

오늘의 예제 깃허브 주소

 

GitHub - nam-su/HandlerExample

Contribute to nam-su/HandlerExample development by creating an account on GitHub.

github.com

 

'Android' 카테고리의 다른 글

커스텀 다이얼로그 (custom Dialog)  (0) 2024.08.18
안드로이드 MVVM 패턴  (0) 2024.04.30
안드로이드 MVP 패턴  (0) 2024.04.29
안드로이드 MVC 패턴  (0) 2024.04.27
안드로이드 ConstraintLayout  (2) 2024.04.25