Computer >> 컴퓨터 >  >> 프로그래밍 >> Android

안드로이드 핸들러(Handler) 완벽 정리: 개념부터 프로그레스 다이얼로그 실전 예제까지

안드로이드 핸들러(Handler)란?

안드로이드에서는 백그라운드 스레드가 메인 스레드(UI 스레드)에 직접 접근할 수 없습니다. UI 갱신은 오직 메인 스레드에서만 수행할 수 있기 때문인데, 이때 핸들러(Handler)가 중간 다리 역할을 담당합니다.

핸들러는 메인 스레드에서 처리해야 할 이벤트들을 큐(Queue) 형태로 수집한 뒤, 이 큐를 루퍼(Looper) 클래스에 전달하여 순서대로 처리하도록 만듭니다. 즉, 백그라운드 스레드에서 발생한 작업 결과를 안전하게 UI에 반영할 수 있게 해주는 통로라고 이해하면 됩니다.

핸들러의 주요 메서드

  • post() — 루퍼를 통해 백그라운드 스레드의 작업(Runnable 객체)을 메인 스레드로 전달합니다. 간단한 UI 업데이트에 주로 사용됩니다.

  • sendMessage() — Message 객체를 활용해 UI로 전달할 내용을 체계적으로 구성하고 관리해야 할 때 사용합니다. 전달된 메시지는 handleMessage()에서 받아 처리할 수 있습니다.

예제: 핸들러로 프로그레스 다이얼로그 진행률 업데이트하기

이번 예제에서는 백그라운드 스레드에서 진행률 값을 계산하고, 핸들러의 post() 메서드를 이용해 프로그레스 다이얼로그(ProgressDialog)의 진행 상태를 실시간으로 갱신하는 방법을 단계별로 살펴보겠습니다.

1단계 — 새 프로젝트 생성

안드로이드 스튜디오에서 File → New Project를 선택하고, 필요한 정보를 모두 입력해 새 프로젝트를 생성합니다.

2단계 — 레이아웃 작성

res/layout/activity_main.xml 파일에 아래 코드를 추가합니다.

<?xml version = "1.0" encoding = "utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android = "https://schemas.android.com/apk/res/android"
   xmlns:app = "https://schemas.android.com/apk/res-auto"
   xmlns:tools = "https://schemas.android.com/tools"
   android:layout_width = "match_parent"
   android:layout_height = "match_parent"
   tools:context = ".MainActivity">
   <Button
      android:id = "@+id/button"
      android:layout_width = "wrap_content"
      android:layout_height = "wrap_content"
      android:text = "Click"
      app:layout_constraintBottom_toBottomOf = "parent"
      app:layout_constraintLeft_toLeftOf = "parent"
      app:layout_constraintRight_toRightOf = "parent"
      app:layout_constraintTop_toTopOf = "parent" />
</android.support.constraint.ConstraintLayout>

3단계 — MainActivity.java 작성

src/MainActivity.java 파일에 아래 코드를 추가합니다.

import android.app.ProgressDialog;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
   Handler mHandler;
   ProgressDialog mProgressBar;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      Button button = findViewById(R.id.button);
      button.setOnClickListener(this);
   }
   @RequiresApi(api = Build.VERSION_CODES.O)
   @Override
   public void onClick(View v) {
      switch (v.getId()) {
         case R.id.button:
         notificationDialog();
         break;
      }
   }
   @RequiresApi(api = Build.VERSION_CODES.O)
   private void notificationDialog() {
      mHandler=new Handler();
      mProgressBar= new ProgressDialog(MainActivity.this);
      mProgressBar.setMax(100);
      mProgressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
      mProgressBar.show();
      new Thread(new Runnable() {
         @Override
         public void run() {
            for (int i = 0; i <= 100; i++) {
               final int currentProgressCount = i;
               try {
                  Thread.sleep(50);
               } catch (InterruptedException e) {
                  e.printStackTrace();
               }
               //백그라운드 스레드의 값을 UI 스레드로 전달해 갱신
               mHandler.post(new Runnable() {
                  @Override
                  public void run() {
                     mProgressBar.setProgress(currentProgressCount);
                  }
               });
            }
         }
      }).start();
   }
}

앱 실행 및 결과 확인

이제 애플리케이션을 실행해 보겠습니다. 실제 안드로이드 기기가 컴퓨터에 연결되어 있다고 가정합니다. 안드로이드 스튜디오에서 프로젝트의 액티비티 파일 중 하나를 연 뒤, 툴바의 Run 버튼을 클릭하세요. 실행 옵션에서 자신의 모바일 기기를 선택하면, 기기 화면에 앱의 기본 화면이 표시됩니다.

안드로이드 핸들러(Handler) 완벽 정리: 개념부터 프로그레스 다이얼로그 실전 예제까지

화면의 버튼을 클릭하면 아래와 같이 프로그레스 다이얼로그가 나타나며, 진행률이 0부터 100까지 순차적으로 올라가는 것을 확인할 수 있습니다.

안드로이드 핸들러(Handler) 완벽 정리: 개념부터 프로그레스 다이얼로그 실전 예제까지


안드로이드 핸들러(Handler) 완벽 정리: 개념부터 프로그레스 다이얼로그 실전 예제까지

참고: ProgressDialog는 더 이상 권장되지 않습니다

예제에 사용된 ProgressDialog는 API 26(안드로이드 8.0 오레오)부터 공식적으로 지원 중단(deprecated)되었습니다. 최신 프로젝트에서는 레이아웃에 ProgressBar 위젯을 직접 배치하거나, DialogFragment를 활용한 커스텀 다이얼로그를 사용하는 것이 좋습니다. 다만 핸들러를 통해 백그라운드 작업 결과를 메인 스레드의 UI에 안전하게 반영한다는 핵심 원리는 동일하게 적용되므로, 핸들러의 동작 방식을 익히는 학습용 예제로는 여전히 유용합니다.