서비스에서 UI 스레드 처리기에 액세스


90

UI 스레드의 처리기에 액세스해야하는 Android에서 새로운 것을 시도하고 있습니다.

다음을 알고 있습니다.

  1. UI 스레드에는 자체 처리기와 루 퍼가 있습니다.
  2. 모든 메시지는 UI 스레드의 메시지 대기열에 배치됩니다.
  3. 루퍼는 이벤트를 선택하여 핸들러에 전달합니다.
  4. 핸들러는 메시지를 처리하고 특정 이벤트를 UI로 보냅니다.

UI 스레드 처리기를 가져 와서이 처리기에 메시지를 넣어야하는 서비스를 갖고 싶습니다. 이 메시지가 처리되어 UI에 발행되도록합니다. 여기서 서비스는 일부 응용 프로그램에서 시작되는 일반 서비스입니다.

이것이 가능한지 알고 싶습니다. 그렇다면 시도해 볼 수 있도록 몇 가지 코드 스 니펫을 제안하십시오.

감사합니다 Girish

답변:


179

이 코드 스 니펫은 기본 (UI) 스레드와 연관된 핸들러를 구성합니다.

Handler handler = new Handler(Looper.getMainLooper());

그런 다음 다음과 같이 기본 (UI) 스레드에서 실행할 항목을 게시 할 수 있습니다.

handler.post(runnable_to_call_from_main_thread);

핸들러 자체가 메인 (UI) 스레드에서 생성 된 경우 간결성을 위해 인수를 생략 할 수 있습니다.

Handler handler = new Handler();

프로세스 및 스레드에 대한 Android 개발자 가이드 에 자세한 정보가 있습니다.


2
그것을 테스트했고 훌륭하게 작동합니다! 사용 사례의 예 : 장치에서 직접 실행되는 서버에서 제공하는 웹 인터페이스가 있습니다. 인터페이스를 사용하여 UI와 직접 상호 작용할 수 있고 서버가 자체 스레드에서 실행되어야하므로 활동 외부에서 UI 스레드를 터치하는 방법이 필요했습니다. 설명하신 방법이 훌륭했습니다.
mrPjer

1
훌륭한. 매력처럼 작동하고 매우 유용합니다. 감사합니다.
JRun

완벽한 ^^ 방금 StreamingService에서 내 UI를 업데이트하는 데 사용했습니다. 정확히 내가 필요한 것 감사합니다!
An-droid

핸들러의 싱글 톤 인스턴스를 생성하고 ui 스레드에서 무언가를 실행할 때마다이를 사용할 수 있는지 알고 있습니까?
HelloWorld

나는 우리가 결코 알지 못할 것이다 추측
데니

28

Messenger첨부 된 개체를 Handler만들고에 전달 Messenger합니다 Service(예 :에 대한 Intent추가 startService()). 는 Service다음을 보낼 수 있습니다 Message받는 Handler비아 Messenger. 다음은이를 보여주는 샘플 애플리케이션 입니다.


이 팁에 감사드립니다. 이것은 도움이되었습니다. 내 활동 MyDemo.dispatchTouchEvent (MotionEvent) 라인에 대한 터치 이벤트 흐름은 다음 스택을 참조하십시오. 20 PhoneWindow $ DecorView.dispatchTouchEvent (MotionEvent) 라인 : 1696 ViewRoot.handleMessage (Message) 라인 : 1658 ViewRoot (Handler) .dispatchMessage (Message ) line : 99 Looper.loop () line : 123 // 이벤트 처리는 여기서 시작됩니다. ActivityThread.main (String []) line : 4203 여기서 ViewRoot는 핸들러입니다. 이 처리기의 참조를 얻고 싶습니다 ... 내 응용 프로그램에서 얻을 수 있습니까?
iLikeAndroid

@iLikeAndroid :를 만들지 않았다면 HandlerAFAIK에 액세스 할 수 없습니다.
CommonsWare

감사합니다. ViewRoot의 인스턴스를 만들려고했습니다. 이것은 핸들러 일뿐입니다. 이제이 핸들러에서 메시지를 발행 할 수 있습니다. 핸들러가 메시지를 받고 있습니다. 그러나 ViewRoot는 제대로 초기화되지 않아 메시지를 처리 ​​할 수 ​​없습니다. ViewRoot에 적절한 데이터를 초기화하려면 ViewRoot.setView ()를 호출해야합니다. 초기화에 사용할 수있는 기본보기 또는 기본보기 등이 있는지 알고 싶습니다.
iLikeAndroid

@iLikeAndroid : ViewRootAndroid SDK에는 AFAICT 가 없습니다 .
CommonsWare 2011 년

1
@ hadez30 : 개인적으로 바운드 서비스를 많이 사용하지 않습니다. Handler/ 를 사용하는 것을 환영합니다 Messenger.하지만 모든 것을 이벤트 버스 (예 : greenrobot의 EventBus)로 바꾸겠습니다.
CommonsWare

4

현재 나는 이런 종류의 문제에 오토 와 같은 이벤트 버스 라이브러리를 사용하는 것을 선호합니다 . 원하는 구성 요소 (활동)를 구독하기 만하면됩니다.

protected void onResume() {
    super.onResume();
    bus.register(this);
}

그런 다음 콜백 메서드를 제공합니다.

public void onTimeLeftEvent(TimeLeftEvent ev) {
    // process event..
}

그런 다음 서비스가 다음과 같은 문을 실행할 때 :

bus.post(new TimeLeftEvent(340));

해당 POJO는 위의 활동 및 기타 모든 구독 구성 요소에 전달됩니다. 간단하고 우아합니다.


3

다음 코드를 시도해 보는 것이 좋습니다.

    new Handler(Looper.getMainLooper()).post(() -> {

        //UI THREAD CODE HERE



    });

OP를 지원하려면 추가 설명이 필요합니다.
Moog

2

다음과 같이 브로드 캐스트 수신기를 통해 값을 얻을 수 있습니다. 먼저 고유 한 IntentFilter를 다음과 같이 만듭니다.

Intent intentFilter=new IntentFilter();
intentFilter.addAction("YOUR_INTENT_FILTER");

그런 다음 내부 클래스 BroadcastReceiver를 다음과 같이 만듭니다.

    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    /** Receives the broadcast that has been fired */
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getAction()=="YOUR_INTENT_FILTER"){
           //HERE YOU WILL GET VALUES FROM BROADCAST THROUGH INTENT EDIT YOUR TEXTVIEW///////////
           String receivedValue=intent.getStringExtra("KEY");
        }
    }
};

이제 방송 수신기를 onResume ()에 다음과 같이 등록하십시오.

registerReceiver(broadcastReceiver, intentFilter);

마지막으로 onDestroy ()에서 BroadcastReceiver를 다음과 같이 등록 취소하십시오.

unregisterReceiver(broadcastReceiver);

이제 가장 중요한 부분은 ... 값을 보낼 필요가있는 곳에서 브로드 캐스트를 시작해야합니다.

Intent i=new Intent();
i.setAction("YOUR_INTENT_FILTER");
i.putExtra("KEY", "YOUR_VALUE");
sendBroadcast(i);

.... 건배 :)


1

에서 kotlin그게 당신이 그것을 할 수있는 방법

서비스에서 토스트 메시지를 표시하려면

val handler = Handler(Looper.getMainLooper())
handler.post {
   Toast.makeText(context, "This is my message",Toast.LENGTH_LONG).show()
}

0

해결책:

  1. 크리에이트 핸들러루퍼 주 스레드에서을 : RequestHandler를을
  2. 만들기 HandlerLooper주 스레드에서 : ResponseHandler에와 재정의 handleMessage방법
  3. requestHandler에 실행 가능한 작업 게시
  4. Runnable태스크 내 에서 responseHandler에서 sendMessage를 호출하십시오.
  5. sendMessage결과 responseHandler에서 handleMessage가 호출됩니다.
  6. 에서 속성 가져 오기 Message및 처리, UI 업데이트

샘플 코드 :

    /* Handler from UI Thread to send request */

    Handler requestHandler = new Handler(Looper.getMainLooper());

     /* Handler from UI Thread to process messages */

    final Handler responseHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {

            /* Processing handleMessage */

            Toast.makeText(MainActivity.this,
                    "Runnable completed with result:"+(String)msg.obj,
                    Toast.LENGTH_LONG)
                    .show();
        }
    };

    for ( int i=0; i<10; i++) {
        Runnable myRunnable = new Runnable() {
            @Override
            public void run() {
                try {
                   /* Send an Event to UI Thread through message. 
                      Add business logic and prepare message by 
                      replacing example code */

                    String text = "" + (++rId);
                    Message msg = new Message();

                    msg.obj = text.toString();
                    responseHandler.sendMessage(msg);
                    System.out.println(text.toString());

                } catch (Exception err) {
                    err.printStackTrace();
                }
            }
        };
        requestHandler.post(myRunnable);
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.