궁금한게 많은 개발자 노트

[ Android ] Service에서 UI 변경하기 본문

App Development

[ Android ] Service에서 UI 변경하기

궁금한게 많은 개발자 2020. 6. 30. 13:17

안드로이드 앱컴포넌트는 Activity와 Service로 구분될 수 있다.
Activity는 UI가 있는 화면을 제공하는 기능, Service는 UI없이 백그라운드에서 실행되는 기능을 주로 담당한다.

안드로이드를 사용중에 UI요소를 주로 관리하는 Activity나 Fragment에서가 아닌
Service에서 UI요소를 건드려야할 필요가 있을 때 Acitvity에서 하던 것처럼 동일하게 Context를 사용하면
되지 않을까해서 시도를 해봤는데 아래와 같은 에러메세지를 출력.

Can't create handler inside thread that has not called Looper.prepare()

 

그래서 어떤의미인지를 찾아보니, Application은 성능향상을 위해 멀티쓰레드를 사용하는데, 
UI를 업데이트하는 행위는 단일 쓰레드(메인 쓰레드)에서만 일어나도록 제한한다.
이유는 멀티 스레드로 UI를 업데이트하면 동일한 UI 자원을 사용할 때
교착상태(deadlock), 경합상태(race condition) 등 여러 문제가 발생할 수 있기 때문이다.

그래서 에러가 발생한 이유는 쓰레드마다 Looper가 존재하고, UI수정을 위한 Handler에서는 메인쓰레드가 필요한데,
메인 쓰레드가 아닌곳에서 호출하다보니 메인쓰레드의 Looper를 가져오지 못해 UI를 수정할 수 없다는 에러였다.

그렇다면, MainThread의 Looper를 가져오는 방법을 사용하여 Handler를  생성하면 가능하지않을까 싶어 검색

Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
    @Override
    public void run() {
        // 원하는 작업 
      }
 }, 0);

Looper.getMainLooper()를 통해 어디서든 MainThread의 Looper를 얻어올 수 있었다.

 

또한, 여기서 중요한 점은 Runnable을 생성하여 그것을 Handler에서 post해준다는 점이다.
Handler를 MainThread와 연관된 Looper를 통해 생성을 시키고, MainThread로 post를 통해 원하는 동작을 수행하는
Runnable객체를 던져주면 MessageQueue에 들어가게 되면서 MainThread에서 UI를 수정하는 작업이 진행된다.
이렇게 해서 Worker Thread에서도 UI를 수정할 수 있는 과정을 알 수 있었다.

 

그 외에도, runOnUiThread를 사용하여 UI를 수정할 수 있다고 한다 :)

 

'App Development' 카테고리의 다른 글

[ Android ] AsyncTask  (0) 2020.11.25
[ Android ] AndroidManifest.xml Permission Check  (0) 2020.07.01
Comments