앞선 포스트에서는 runnable, handler를 살펴보았다면 이와 함께 runnable을 ui thread위에 실행시킬 수 있는 다른 방법들을 함께 알아보도록 하자. 해당 방법은 총 네가지로 알려져있는데, 다음과 같다.
1. Handler.post()
2. view.post()
3. Activity.runOnUiThread()
4. AsyncTask
Handler.post()
runnable의 개념과 핸들러로 runnable을 보내는 법은 이전 포스트 를 참고하면 되고, 간략하게는 핸들러를 통해 runnable을 UI 스레드로 보내고, 실행시킨다.
View.post()
Causes the Runnable to be added to the message queue. The runnable will be run on the user interface thread.
public boolean post (Runnable action)
이 포스트를 작성하게 된 계기로, 진행중인 프로젝트에서 이 view.post()를 실행 순서 보장에 사용해 문제를 해결하고 코드를 개선했다.
[refactor] 마이페이지 / 로딩프로그레스바 - 애니메이션 간의 실행순서 보장 로직 개선 by sxunea · Pu
closed #290 📝 Work Description 문제 상황은 저번 PR을 참고해주세요 ! 저때 delay를 통해 100ms동안 강제로 기다리게해 로딩프로그레스바 비가시화 -> 데이터 불러와 애니메이션 시작 이라는 순서를 보장
github.com
View Class API 에 구현되어있고, 역할은 위의 handler.post()와 같다. 다만, handler.post()가 특정 스레드의 핸들러에 연결된 메시지 큐에 runnable을 담아 전달한다면, view.post()는 뷰가 속한 스레드의 메시지 큐에 runnable을 담는다는 차이가 있다.
또, post를 자세히 살펴보면
View.post()가 호출되는 시점에서 View가 이미 화면에 그려진 상태(즉, onAttachedToWindow()가 호출된 후)여야 runnable이 바로 실행될 수 있다. 따라서 View가 아직 화면에 그려지지 않았거나, 레이아웃 과정이 진행 중이라면, 실행이 레이아웃 과정이 완료된 후로 지연되므로 실행시점의 차이를 잘 안다면 뷰와 관련된 작업에는 더욱 안전하게 사용할 수 있다.
Activity.runOnUiThread()
Runs the specified action on the UI thread. If the current thread is the UI thread, then the action is executed immediately. If the current thread is not the UI thread, the action is posted to the event queue of the UI thread.
public final void runOnUiThread (Runnable action)
다음은 runOnUiThread()이다. 공식문서의 설명처럼, 이 방식과 앞선 두개의 post 방식의 차이는 handler는 post 방식을 통해 매번 이벤트를 발생시킨다면, runOnUiThread는 현재 시점이 UI 스레드이면 바로 실행시킨다는 것이다. 만약 현재 스레드가 UI 스레드가 아니라면 해당 작업은 큐에 들어가서 현재 스레드가 UI 스레드가 될때까지 멈추고 기다리게 된다.
마찬가지로 runOnUiThread의 내부를 살펴보면, 명시한 것 과 같이 현재스레드가 UI 스레드인지를 확인하고, 맞다면 handler.post() 로 runnable을 전달한다.
AsyncTask
알아보기 전에, 먼저 밝히고자 하는 것은 asyncTask는 2019년 기준 deprecated되었고, 따라서 asyncTask의 사용법 보다는 동작 방식과 한계를 중점으로 남기고 넘어가도록 하자.
asyncTask 클래스를 상속받아 클래스를 만들면 그 안에 스레드를 위한 코드와 UI 접근 코드를 함께 넣을 수 있다.
AsyncTask was intended to enable proper and easy use of the UI thread.
asyncTask는 다양한 메소드들을 가지고 별도의 스레드에서 수행해야할 기능들을 클래스 하나로 묶어서 실행시킬 수 있다는 장점이 있지만 다음과 같은 단점과 한계가 존재해 deprecated 되었다.
- task는 한번만 실행되어 재사용이 블가능하다 -> 효율 좋지 않음
- 종료를 직접 해주지 않으면 메모리 누수가 발생한다
- execute()는 UI 스레드에서 직접 호출해야한다
- 안드로이드 API 버전 별로 동작이 다르다
- 순차적으로 실행되므로 속도가 느릴 수 있다
- 화면 회전과 같이 configuration change가 일어나면, 액티비티가 새로 생성되면서 기존의 asyncTask 위에 asyncTask가 다시 실행되어 중첩된다. 이는 역시 메모리 누수의 가능성이 높다
이렇게 deprecated된 asyncTask를 제외하면, 총 세가지 방법은 UI 스레드에서 runnable을 실행시킬 수 있다. 언뜻 보면 비슷해보이지만 내부 코드를 파악했다면 상황에 맞게 적절하게 사용하면 좋을 것 같다
참고자료
Android: What's the difference between Activity.runOnUiThread and View.post?
What's the difference between Activity.runOnUiThread and View.post, could someone, please, explain?
stackoverflow.com
[Android] AsyncTask 가 떠나간 이유
우리의 옛사랑 AsyncTask 의 사인 파헤쳐보기
velog.io
'안드로이드 > 꺼진개념다시보기' 카테고리의 다른 글
[Android] 안드로이드 UI 어디까지 아는데 ? - (1) dp, 해상도와 DIP & 픽셀 단위의 이해 (0) | 2024.08.24 |
---|---|
[Android] viewModelScope, lifecycleScope과 repeatOnLifecycle (0) | 2024.07.10 |
[Android] Serializable, Parcelable (0) | 2024.07.07 |
[Android] 안드로이드의 UI 상태 저장, onSaveInstanceState (0) | 2024.07.07 |
[Android] Thread, Handler와 Looper (0) | 2024.05.06 |