핸들러에 대해 설명한 글을 보고 오시면 더 이해하기 좋을 것 같습니다.
2024.05.09 - [안드로이드] - [Android] 핸들러(Handler)
[Android] 핸들러(Handler)
안드로이드의 스레드는 두 가지가 존재합니다. 먼저, 일반적인 코드처리, 화면을 갱신하는 처리 등을 담당하는 메인스레드(UI 스레드)스레드 클래스를 사용해서 백그라운드에서 작업을 처리하
goharry.tistory.com
제가 적은 핸들러 관련 글을 같이 첨부해 놓겠습니다.
핸들러 정리
핸들러의 사용 이유에 대해 다시 한번 간략하게 정리해 보면
안드로이드에서는 하나의 프로세스 안에서 동시에 수행되어야 하는 작업을 위해 작업 스레드를 사용하게 되는데, 이 작업스레드는 UI 변경 등의 행동을 할 수가 없습니다.
이때 작업스레드에서 메인스레드로 메시지( ex) UI 변경에 관한 작업 )를 전달해 주는 역할을 하는 클래스를 핸들러 합니다.
핸들러 예제
다른 작업스레드에서 보낸 메시지를 텍스트 뷰에 띄우기
단순하게 작업스레드에서 보낸 메세지를 핸들러를 통해 textView의 텍스트로 설정해 주는
아주아주 간단한 UI 변경 예제라고 볼 수 있겠습니다.
1. XML
간단하게 텍스트 뷰만 하나 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello!"
android:textSize="50sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
2. MainActivity
class MainActivity : AppCompatActivity() {
//늦은 초기화들
private lateinit var binding: ActivityMainBinding
private lateinit var handler: Handler
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setHandler()
setThread()
}
// 텍스트 뷰의 텍스트 set
private fun setText(text: String) {
binding.textView.text = text
}
// 작업스레드의 메세지를 Handler에서 처리
private fun setHandler() {
handler = Handler(Looper.getMainLooper()) {
// 메시지 처리
val data = it.obj as String
setText(data)
true
}
}
//작업스레드에서 메인스레드로 핸들러 sendMessage 메서드를 통해 메세지 전송
private fun setThread() {
// 새로운 작업 스레드에서 핸들러로 메시지 전송
Thread {
// 메시지 생성 및 전송
val message = Message.obtain().apply {
obj = "hello Harry"
}
handler.sendMessage(message)
}.start()
}
}
3. 결과
계속해서 UI 변경하는 예제
텍스트 리스트에 있는 텍스트들을 1초마다 새로 textView에 갱신해 주는 예제라고 생각하시면 됩니다.
1. XML
위와 동일합니다.
2. MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var handler: Handler
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setHandlerRepeatWork()
}
private fun setText(text: String) {
binding.textView.text = text
}
private fun setHandlerRepeatWork() {
// 핸들러 생성
handler = Handler(Looper.getMainLooper())
// 반복 작업 시작
val texts = listOf("Hello", "Harry", "Bye", "Harry") // 예시로 사용할 텍스트들
var index = 0 // 텍스트 리스트의 인덱스
val runnable = object : Runnable {
override fun run() {
// setText 메서드를 호출하여 다음 텍스트 설정
setText(texts[index])
// 인덱스 증가 및 범위 초과 시 초기화
index = (index + 1) % texts.size
// 핸들러에 다시 작업 예약
handler.postDelayed(this, 1000) // 1초마다 반복
}
}
// 반복 작업 예약
handler.post(runnable)
}
}
3. 결과
짜잔!!
지금까지 핸들러를 사용하는 방법에 대해서 아주아주 간단한 예제와 함께 알아보았습니다.
서버와 통신해야 되는 작업 등도 핸들러를 통해서 많이들 작업을 하게 되는데요.
Handler가 Deprecated 되었다고?!
그런데 어디선가 Handler가 deprecated 되었다는 이야기를 들었습니다.
좀 찾아보니까, Handler가 생성되는 동안, Looper가 암묵적으로 선택되면 여러 가지 버그가 발생할 수 있다고 한다.
이러한 가능성을 차단하기 위해서는 명시적으로 Looper를 선언해야 하므로, Handler()와 Handler(Handler.Callback)이 deprecated 된 것 같다.
저렇게 명시적으로 Looper를 선언해 주면 해결이기도 하고,
다른 방법으로는 코루틴이라는 좋은 친구가 있는데요.
코루틴에 대해서 다음번에 꼭 블로그 포스팅을 꼭 해봐야겠습니다!!
'안드로이드' 카테고리의 다른 글
[Android] Glide 3 - 원형 이미지에 로딩 애니메이션 구현 (4) | 2024.07.29 |
---|---|
[Android] Glide 2 - 로딩 애니메이션 구현 (0) | 2024.07.27 |
[Android] 핸들러(Handler) (0) | 2024.05.09 |
[Android] MVC 패턴 예제! (0) | 2024.05.04 |
[Android] 디자인 패턴 이해 (MVC/MVP/MVVM) (0) | 2024.04.30 |