RP2 week4 - Thread) 2021.01.21

Star·2021년 1월 22일
0

2021.01.20

이번주는 저번주만큼 열심히 하질 못하고 있다. 조금 방심하니 미루게 된다. 나를 위하는 것보다 남에게 보여준다는 생각이 더 컸던 것 같다. 민망해서 이번주는 안쓰려다가 더 안할 것 같아서 늦게나마 쓰기 시작한다.

1월 20일 수요일에 두더지 잡기 베이스에 '장난치지 말아요' 라는 게임의 컨셉을 더하는 걸로 확정짓고, 화면 UI로 사용할 리소스 파일들을 따고 게임 화면을 구성했다.

2021.01.21

📋 Plan

  1. 타이머를 구현한다. / 스레드를 사용해서 각 ImageView마다 두더지가 올라오는 것과 같은 움직임을 만든다. => 예상 시간) 6시간
  2. (캐릭터 터치를 성공할 때 보여줄 타격 효과를 만든다: 타격음, 점수 증가, 선생님이 뒤돌아보는 이미지로 변경 => 예상 시간) 2시간)

📚 결과

1.타이머

참고) https://jung-story.tistory.com/34

run()을 오버라이드하여 TimerTask 인터페이스를 구현한 후, Timer 클래스 인스턴스를 사용하여 타이머를 실행시킨다.

var timer = Timer()
var timerTask: TimerTask
var time = 60
var ms = 0

// run()을 오버라이드하는 TimerTask 인터페이스를 구현한다 
timerTask = object : TimerTask() {	// 익명 객체 생성
    override fun run() {
    	ms -= 1 
    	if(ms <= 0){    // 1초 경과
           ms += 100	// -1ms -> 99ms
           time -= 1    // 1초 감소시킨다
                
             // 60초 모두 경과 타이머 정지
             if(time <= 0){
                 time = 0
                 ms = 0
                 cancel()
             }
         }
         // 10ms 단위로 남은시간 업데이트, UI 업데이트는 메인 스레드에서 한다
         runOnUiThread{
            scoreView.text = String.format("%02d.%02d",time,ms)
            timeLeftBar.progress -= 1
         }
     }
}
timer.schedule(timerTask,10,10) // 10ms 후에 시작, 10ms 단위로 실행

2. 스레드

예제를 보고 바로 사용해보려고 하니 동작 방식이 좀 알송달송했다. 그래서 아예 안드로이드 스레드에 대해 먼저 자세히 알아봤다. 그리고 이해가 되기 시작했다.
참고) https://recipes4dev.tistory.com/143?category=768056

  • 프로그램이란? 명령어와 데이터의 집합으로 구성되어 저장장치에 저장되어있는 코드를 의미한다.

  • 프로세스란? 운영체제에 의해 메모리에 로드되어 실행중인 상태에 있는 프로그램을 말한다.

  • 그러면 스레드란 무엇인가? 스레드는 프로세스 안에서 각각의 '독립적인 실행 흐름'을 말한다.

  • 스레드는 왜 필요한가?
    모든 프로그램은 시작~종료까지 적어도 하나의 실행 흐름을 가지고 있다.
    게다가 모바일 앱의 경우, 화면 터치등의 사용자와 상호작용이 잦기 때문에 하나의 실행 흐름만으로는 앱을 구성하기 힘들다. 따라서 2개 이상의 실행흐름을 사용, 즉 멀티스레드 필요하다.

  • 안드로이드에서 스레드를 만드는 방법

    1. Thread 클래스 상속

    2. Runnable 인터페이스 구현

      두 방법 모두 run 메서드를 오버라이드 하며, 성능은 동일하다.

      일반적으로 run 메서드만 오버라이드하면 되거나 다중 상속이 불가능한 경우 Runnable, run() 외에 Thread 기능을 확장해야 한다면, Thread 클래스를 상속하는 방법을 쓰는 것이 권장된다.

  • 메인 스레드란?
    프로세스가 시작됨과 동시에 반드시 실행시키는 스레드를 '메인 스레드'라고 한다. 또한 화면 UI를 그리고, 업데이트 하는 작업은 반드시 메인스레드에서 이뤄지고, 또 그래야만 하기 때문에 UI 스레드라고 부르기도 한다.

  • 왜 메인 스레드에서만 화면을 조작하는 것이 가능할까?
    예를 들어, 중첩된 View가 있을 경우, 여러 스레드에서 중첩 View를 각각 그릴 경우, View가 그려지는 순서에 따라 화면이 다르게 나타날 수 있다. 즉, 충돌의 가능성이 있기 때문에 화면은 반드시 메인 스레드에서만 그리도록 되어있다.

  • 그러면 메인 스레드가 아닌 워커 스레드에서는 어떻게 View를 처리할 수 있을까?
    Handler와 Message 객체를 사용하여 스레드 간 통신을 한다.

  • Looper, MessageQueue, Handler, Message란?

    1. MessageQueue - Message(메시지, 이벤트)가 발생했을 때 저장되는 자료구조로, 메인스레드에 존재한다. 개발자가 직접 구현할 일은 거의 없다.

    2. Looper - 메인 스레드에서 메시지 큐의 메시지 수신을 대기하는 역할로, 메시지 발생시 Handler(핸들러)를 호출하여 메시지를 처리한다. 개발자가 직접 구현하는 일은 거의 없다.

    3. Handler - 앱에서 화면 업데이트, 사용자 입력 등의 message(메시지, 이벤트)가 발생했을 때, 그 메시지에 매핑되어서 그것을 처리할 때 사용되며, 메시지큐에 메시지를 전달하는 역할도 함께 한다.

      스레드에서 핸들러를 생성하면 그 핸들러는 해당 스레드와 메시지큐에 각각 연결된다.

    4. Message - 데이터를 식별하는 식별자, 데이터들, 기타 객체를 포함할 수 있으며, 스레드 간 통신을 할 때 사용된다. 메시지를 처리할 핸들러를 사용하여 메시지를 보내면, 메시지큐에 전달되고, Looper가 매핑된 핸들러를 호출하여 메시지를 처리한다.

  • 메인 스레드에서는 긴 작업을 수행해선 안된다.
    Looper와 MessageQueue의 이유로 만약 메인 스레드에서 무한 루프나 긴 작업을 수행할 경우, 그동안 메시지 큐의 메시지 수신을 확인하고 처리하는 것이 불가능하기 때문이다.
    (ex: 화면이 멈추거나 터치가 먹히지 않는다.)

    따라서, 긴 작업은 워커 스레드에서 작성해야 한다.


✂ Reflection

타인의 시선이 아니다,

나를 위해 하고있는 거다.

profile
To be Developer

0개의 댓글