상상하라 그리고 현실로 만들어라.

상상하는 모든 것이 미래다.

Kotlin과 Android/Android

코틀린으로 안드로이드 스레드(Thread) 한방에 끝내기

월터제이(Walter J) 2020. 12. 1. 09:00

안녕하세요, 반갑습니다!

 

한 개의 프로그램(프로세스) 에서는 많은 스레드를 동시에 처리할 수 있지요.

그리고 프로세스의 메모리 또한 공유합니다.

프로세스로부터 각 메모리를 할당 받은 스레드는 독립적으로 실행됩니다.

 

안드로이드 역시 1개의 앱(프로그램)에서 여러개의 스레드를 사용할 수 있는데요.

예를 들어

음악을 들을 때,

다운로드를 받을 때,

푸쉬 알림 등 이 모두 스레드를 이용한 기능입니다.

 

오늘은 기본적인 스레드의 생성방법과 스레드내에서 위젯 등 UI에 결과를 반영하는 방법에 대해 정리해보겠습니다.

 

 

스레드(Thread)

&

UI 에 접근하기

 

 

 

1. 메인 스레드

액티비티를 포함해 모든 컴포턴트가 실행되는 오직 1개만 존재하는 스레드입니다.

그래서 메인 스레드엔 제약사항이 몇 가지 있습니다.

 

  • 화면의 UI 를 그리는 처리를 담당합니다.
  • UI와 상호 작용하고, 이벤트 결과를 사용자에게 보여줍니다.
  • UI 이벤트 등 작업에 일정시간 동안 응답이 없으면 *ANR 팝업을 표시합니다. (ANR : 응용 프로그램이 응답하지 않음)

사용자가 불편함을 느끼지 않도록 안드로이드는 지속적으로 상호작용을 해야합니다.

그래서 이러한 제약사항이 없다면, 사용자는 조금이라도 느린 반응에 불편함을 호소할 수 있겠지요.

 

2. 백그라운드 스레드

메인 스레드가 UI 처리 및 사용자와의 상호작용을 한다면,

백그라운드 스레드는 그 나머지를 모두 맡아서 처리합니다.

이를테면, 네트워크 작업 및 파일 다운로드 등 시간이 오래 걸리는 작업들이지요.

그래서 안드로이드는 종료 시간을 알 수 없는 작업들에 대해서는 이 백그라운드 스레드에서 처리하길 권장하고 있습니다.

 

3. 스레드 만들어보기

Thread

기본적인 스레드 생성 방법입니다.

아래와 같이 만들 수 있고, 실행하면 i 가 10번 찍히는 것을 확인할 수 있습니다.

class ThreadTest : Thread() {
    override fun run() {
        var i = 0

        while (i < 10) {
            i += 1
            Log.i("TreadTest", "i = ${i}")
        }
    }
}

 

Runnable Thread

기능상 위의 스레드와 차이는 없습니다.

하지만 Thread() 를 상속받으면 기타 다른 클래스를 상속받을 수 없다는 단점이 있습니다.

반면 Runnable 을 상속받은 스레드는 다른 클래스도 구현할 수 있도록 지원하는 모델입니다.

그래서 이 Runnable 을 상속받은 스레드를 구현하는 것이 일반적입니다.

class RunnableTest : Runnable {
    override fun run() {
        var i = 0

        while (i < 10) {
            i += 1
            Log.i("RunnableTest", "i = ${i}")
        }
    }
}

 

코틀린의 thread()

코틀린에서는 조금 더 간편하게 Thread() 를 사용할 수 있습니다.

thread() 안에 파라미터를 start=true 로 전달하면 블럭안의 코드를 실행할 수 있습니다.

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        .
        .
        .
        
        thread(start = true) { //'kotlin.concurrent.thread' 를 import 해야함.
            var i = 0

            while(i < 10) {
                i += 1
                Log.d("Main", "i = ${i}")
            }
        }
    }
}

 

이렇게 메인 스레드와는 별개로 작동하는 스레드를 만들어봤는데요.

 

안드로이드는 메인 스레드가 아닌 스레드에서는 UI에 접근할 수 없는 치명적인 규칙이 있습니다.

즉, 다른 스레드내에서 TextView 에 접근할 수 없다는 것이지요.

이제 스레드에서 처리한 작업을 UI에 반영할 수 있도록 하겠습니다.

 

4. runOnUiThread 로 UI 에 접근하기

가볍게 Thread.sleep() 함수를 사용해서 초단위로 TextView에 반영한 코드입니다.

이렇게 runOnUiThread 를 사용해서 간단하게 UI에 접근할 수 있습니다.

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        .
        .
        .
        
        thread(start = true) { 
            var i = 0

            while(i < 10) {
                i += 1
                
                runOnUiThread {    //Ui에 접근할 수 있음
                    textView.text = "카운트 : ${i}"
                }
                
                Thread.sleep(1000)	//1000 == 1초
            }
        }
    }
}

 

 

 

기본적인 스레드 생성방법과 UI 에 접근하는 방법을 정리해봤는데요.

사실 runOnUiThread 는 간단한 방법입니다.

스레드의 결과를 UI 에 접근해서 조작하는 정석? 방법은 따로 있지요

바로 루퍼(Looper)와 핸들러(Handler)인데요.

차후 이 두가지를 포함해 조금 더 심도있게 스레드를 다뤄보겠습니다.

 

감사합니다.

반응형