ANDROID/Android 앱 프로그래밍

[Android] 스레드(Thread)로 메시지 전송하기

주 녕 2021. 6. 22. 17:55
728x90

모든 내용은 Do it! 안드로이드 앱 프로그래밍을 바탕으로 정리한 것입니다. 

 

스레드로 메시지 전송

이전 포스팅에서는 새로운 스레드(Thread) → 메인 스레드(Main Thread)로 메시지를 전달하는 기능을 소개함

∵ 별도의 스레드에서 메인 스레드가 관리하는 UI 객체에 직접 접근할 수 없기 때문

 

[Android] 핸들러(Handler)

모든 내용은 Do it! 안드로이드 앱 프로그래밍을 바탕으로 정리한 것입니다. 핸들러(Handler) 새로운 프로젝트를 만들면 자동으로 생성되는 메인 액티비티는 앱이 실행될 때 하나의 프로세스에서

junyoung-developer.tistory.com

 

🤷‍♀️ 메인 스레드 → 별도의 스레드로 메시지를 전달하는 방법?

  1. 메인 스레드에서 변수를 선언하고 별도의 스레드가 그 값을 읽어가는 방법 → 🙅‍♀️
  2. 루퍼(Looper)를 이용하여 값을 전달하는 방법 

  • 별도의 스레드가 관리하는 동일 객체를 여러 스레드가 접근할 때는 별도의 스레드 안의 메시지 큐를 이용해 순서대로 접근해야 함
  • 핸들러가 처리하는 메시지 큐는 루퍼(Looper)로 처리되는데, 그 과정은 일반적인 이벤트 처리 과정과 유사함
    • 루퍼(Looper)는 메시지 큐에 들어오는 메시지를 지속적으로 보면서 하나씩 처리함
    • 메인 스레드는 UI 객체들을 처리하기 위해 메시지 큐와 루퍼를 사용함
    • 별도의 스레드를 새로 만들었을 때는 루퍼가 없음
    • 메인 스레드나 다른 스레드에서 메시지 전송 방식으로 스레드에 데이터를 전달 후 순차적으로 작업을 수행하려면 루퍼를 만들고 실행해야 함

 

[예제]

public class LooperActivity extends AppCompatActivity {

    EditText editText;
    TextView textView;

    Handler handler = new Handler();

    ProcessThread thread;

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

        editText = findViewById(R.id.looper_edittext);
        textView = findViewById(R.id.looper_textview);

        Button button = findViewById(R.id.looper_btn);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String input = editText.getText().toString();
                Message message = Message.obtain();
                message.obj = input;
                
                // 새로 만든 스레드 안에 있는 핸들러로 메시지 전송
                thread.processHandler.sendMessage(message);
            }
        });

        thread = new ProcessThread();
    }

    class ProcessThread extends Thread {
        ProcessHandler processHandler = new ProcessHandler();

        @Override
        public void run() {
            super.run();
            Looper.prepare();
            Looper.loop();
        }
    }

    class ProcessHandler extends Handler {
        @Override
        public void handleMessage(@NonNull Message msg) {
            // 새로 만든 스레드 안에서 전달받은 메시지 처리
            super.handleMessage(msg);
            final String output = msg.obj + " from thread.";
            handler.post(new Runnable() {
                @Override
                public void run() {
                    textView.setText(output);
                }
            });
        }
    }
}
  • 메인 스레드에서 새로 만든 별도의 스레드로 Message 객체를 전송하고, 별도의 스레드에서는 전달받은 문자열에 다른 문자열을 덧붙여 메인 스레드 쪽으로 다시 전송하는 과정
    • 버튼을 클릭하면 EditText에 있는 문자열을 Message 객체의 obj 변수에 할당
    • Message 객체는 Message.obtain() 메서드를 이용하여 참조함
    • 새로 만든 스레드의 handler 변수를 이용해서 sendMessage() 메서드를 호출하면 메시지 객체가 스레드로 전송됨
    • ProcessThread 클래스를 정의할 때 ProcessHandler 객체를 만들고 Looper.prepare()과 Looper.loop() 메서드를 호출하였기 때문에 이 스레드에서는 Message 객체를 전달받을 수 있음
    • ProcessHandler 클래스에 정의된 handleMessage() 메서드에서는 전달받은 Message 객체의 obj 변수에 들어있는 문자열을 이용하여 새로운 문자열을 만들고 메인 스레드의 핸들러 객체를 통해 텍스트를 표시함

 

 

728x90