본문 바로가기
안드로이드 자바

[JAVA][Android] 핸들러를 사용해 원형프로그래스바를 실행하고, 종료시 토스트 메시지 띄우기

by teamnova 2022. 1. 21.

이번시간에는 핸들러를 사용해 원형프로그래스바를 실행하고, 

종료시 finish 토스트 메시지를 띄우는 작업을 해보겠습니다. 

핸들러에게 메시지를 나눠서 보낼수있습니다.

 

만들 예제 이미지 -> 프로그래스바가 5초 회전후 종료시 finish토스트를 출력하는 모습

https://stickode.com/detail.html?no=2748 

 

https://stickode.com/detail.html?no=2748

 

stickode.com

스틱코드에서 해당 코드를 즐겨찾기해 사용할수 있습니다. 즐겨찾기를 해주세요~

 

 

프로그래스바를 1초마다 실행시키기위해서는 쓰레드를 생성해야합니다.

쓰레드란 무엇일까요?

쓰레드란, 동시작업을 위한 하나의 독립적인 실행단위입니다.

쓰레드는 하나의 프로세스안에서 동시에 수행되어야 하는 작업을 위해서 필요합니다.

 

앱을 실행하면 메인스레드라는 하나의 쓰레드가 실행이 되는데,

사용자가 메인쓰레드 이외에 필요에 따라 직접 새로운 쓰레드를 만들어 사용할 경우에는 UI에 대한 접근이 필요 합니다.

이때 메인쓰레드가 아닌 쓰레드가 리소스에 직접 접근을 하게 되면 문제가 발생합니다.

그 이유는 시스템에서 메인쓰레드와, 새로 만든 쓰레드들간에 어떤순서로 작업을 해야할지 판단 할수 없기 때문입니다.

그래서 핸들러를 사용해서, 우선순위를 정해서 선입선출로 처리를 해주어야 합니다.

 

메인쓰레드 외에 다른 작업쓰레드들은 별도의 제어가 필요합니다. 

이때, UI를 다룰때 핸들러를 사용합니다.

 

이미지출처 - https://www.boostcourse.org/mo316/lecture/259219?isDesc=false

 

핸들러는 각각의 쓰레드 안에 만들수 있습니다.

다른 쓰레드에서 요청하는 정보를 메시지 큐를 통해 순서대로 실행시켜줍니다. 이로서 리소스에 대한 동시 접근의 문제를

해결할수 있습니다. 메인 쓰레드 안에 핸들러를 만들어 놓으면 다른 스레드에서는 특정작업을  먼저 핸들러에게 요청합니다.

핸들러는 메시지큐를 통해 순차적으로 메인스레드에서 처리할 메시지를 전달하는 역할을 합니다.

 

 

 프로그래스바를 만들기위해 XML를 작성하겠습니다.

원형모양의 프로그래스바를 생성

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

    xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"

    >

    <ProgressBar
        android:layout_marginTop="400dp"
        android:id="@+id/ProgressBar"
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">

    </ProgressBar>

</LinearLayout>

 

그리고 액티비티안에 쓰레드와 핸들러를 작성해보겠습니다.

쓰레드를 생성하고, 핸들러클래스를 작성합니다. 쓰레드 안에 핸들러에게 메시지를 보내는 코드를 작성합니다

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.example.myapplication.R;

public class PracticeActivity extends AppCompatActivity {

    ProgressBar progressBar;
    MyHandler handler;

    // 메시지의 종류에 따라 다른 작업을 하기 위해 INCREMENT_PROGRESS 와 FINISH_PROGRESS 상수는 선언
    public static final int INCREMENT_PROGRESS = 0;
    public static final int FINISH_PROGRESS = 1;


    /**
     * Called when the activity is first created.
     */

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_practice);
        // 프로그래스바
        progressBar = (ProgressBar) findViewById(R.id.ProgressBar);
        // 핸들러 생성
        handler = new MyHandler();

        // 1초마다 핸들러에게 메시지를 보내는 쓰레드 생성.
        new Thread() {

            @Override
            public void run() {
                try {
                    for (int i = 0; i < 5; i++) {
                        sleep(1000);
                        // 메시지를 받은 핸들러가 프로그래스바를 진행시킴
                        // for문을 돌때마다
                        // obtainMessage()메소드는 핸들러로부터 메세지를 하나요청
                        // sendMessage() 는 Message Queue 에 넣는 역할
                        handler.sendMessage(handler.obtainMessage(INCREMENT_PROGRESS));
                    }
                    // 핸들러가 종료되었을때, 보내는 메시지.// obj로 토스트 메시지에 띄울 finish라는 텍스트를 보냄
                    handler.sendMessage(handler.obtainMessage(FINISH_PROGRESS, "finish"));

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

    }


// 핸들러 클래스 작성, sendMessage로부터 메시지를 구분해 받아 실행함.
    class MyHandler extends Handler {

        @Override

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case INCREMENT_PROGRESS:
                    progressBar.incrementProgressBy(5);
                    break;
                case FINISH_PROGRESS:
                    Toast.makeText(getApplicationContext(), (String) msg.obj, Toast.LENGTH_SHORT).show();
                    break;
            }
            super.handleMessage(msg);// handleMessage() 메소드에 정의된 기능이 실행
        }

    }
}

메시지의 종류애 따라 다른 작업을 하기위해서 INCREMENT_PROGRESS 와 FINISH_PROGRESS를 선언해주었습니다.

1초마다 핸들러에게 메시지를 보내는 쓰레드를 작성하고, 하단에 핸들러 클래스를 작성합니다.

메시지를 받은 핸들러가 for문을 돌때마다 INCREMENT_PROGRESS를 요청하고,

종료시 FINISH_PROGRESS를 요청합니다.

 

  • obtainMessage()메소드는 호출결과로 메시지 객체를 리턴받음
  • sendMessage() 는 Message Queue 에 넣는 역할
  • handleMessage() 메소드에 정의된 기능을 실행

 

쓰레드에서 핸들러로 메시지를 보내려면,  Message객체를 사용합니다.

Message객체를 obtainMessage 메소드로 참조한 후 sendMessage 메시지를 이용해 핸들러로 보내면 handleMessage 메소드가 자동으로 호출되기 때문에 전달된 Message 객체를 처리할 수 있습니다.

이 때 handleMessage 메소드는 메인 스레드에서 실행됩니다.

 

결과물

 

스틱코드를 활용해서 만들어보세요!

https://stickode.com/detail.html?no=2748 

 

https://stickode.com/detail.html?no=2748

 

stickode.com