Programing

다른 스레드의 메인 스레드에서 코드 실행

lottogame 2020. 3. 17. 08:31
반응형

다른 스레드의 메인 스레드에서 코드 실행


안드로이드 서비스에서 백그라운드 작업을 수행하기위한 스레드를 만들었습니다.

스레드가 기본 스레드의 메시지 대기열에 특정 작업을 게시 해야하는 상황이 있습니다 (예 : a) Runnable.

Handler메인 스레드 를 가져 와서 다른 스레드에서 게시 Message/ 게시 하는 방법이 Runnable있습니까?

감사,


참고 :이 답변은 많은 주목을 받았으므로 업데이트해야합니다. 원래 답변이 게시 된 이후 @dzeikei의 의견은 원래 답변만큼이나 많은 주목을 받았습니다. 가능한 해결책은 다음과 같습니다.

1. 백그라운드 스레드에 Context객체에 대한 참조가있는 경우 :

백그라운드 워커 스레드가 컨텍스트 오브젝트에 액세스 할 수 있는지 확인하십시오 (응용 프로그램 컨텍스트 또는 서비스 컨텍스트 일 ​​수 있음). 그런 다음 백그라운드 작업자 스레드 에서이 작업을 수행하십시오.

// Get a handler that can be used to post to the main thread
Handler mainHandler = new Handler(context.getMainLooper());

Runnable myRunnable = new Runnable() {
    @Override 
    public void run() {....} // This is your code
};
mainHandler.post(myRunnable);

2. 백그라운드 스레드에 Context객체가 없거나 필요한 경우

(@dzeikei에서 제안 함) :

// Get a handler that can be used to post to the main thread
Handler mainHandler = new Handler(Looper.getMainLooper());

Runnable myRunnable = new Runnable() {
    @Override 
    public void run() {....} // This is your code
};
mainHandler.post(myRunnable);

아래의 주석가가 올바르게 지적했듯이 이것은 서비스의 일반적인 솔루션이 아니며 활동에서 시작된 스레드 (서비스는 그러한 스레드 일 수는 있지만 모든 스레드는 아닙니다)입니다. 서비스 활동 커뮤니케이션의 복잡한 주제에 대해서는 공식 문서의 전체 서비스 섹션을 읽으십시오-복잡하기 때문에 기본 사항을 이해하는 것이 좋습니다 : http://developer.android.com/guide/components/services.html # 알림

아래 방법은 가장 간단한 경우에 작동 할 수 있습니다.

올바르게 이해하면 응용 프로그램의 GUI 스레드에서 일부 코드를 실행해야합니다 ( "메인"스레드라는 다른 것을 생각할 수 없음). 이를 위해 다음과 같은 방법이 있습니다 Activity.

someActivity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
           //Your code to run in GUI thread here
        }//public void run() {
});

문서 : http://developer.android.com/reference/android/app/Activity.html#runOnUiThread%28java.lang.Runnable%29

이것이 당신이 찾고있는 것이기를 바랍니다.


컨텍스트에 액세스 할 수없는 경우 다른 간단한 방법이 있습니다.

1). 메인 루퍼에서 핸들러를 만듭니다.

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

2). Runnable 인터페이스를 구현하십시오.

Runnable runnable = new Runnable() { // your code here }

삼). Runnable을 uiHandler에 게시하십시오.

uiHandler.post(runnable);

그게 전부입니다 ;-) 스레드와 함께 즐거운 시간을 보내지 만 동기화하는 것을 잊지 마십시오.


스레드에서 코드를 실행하는 경우 (예 : 일부 작업 지연) runOnUiThread컨텍스트에서 호출해야합니다 . 예를 들어 코드가 MainActivity클래스 내부에 있으면 다음을 사용하십시오.

MainActivity.this.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        myAction();
    }
});

메인 (UI 스레드) 또는 다른 스레드에서 메소드를 호출 할 수 있다면 다음과 같은 검사가 필요합니다.

public void myMethod() {
   if( Looper.myLooper() == Looper.getMainLooper() ) {
       myAction();
   }
   else {

}

압축 코드 블록은 다음과 같습니다.

   new Handler(Looper.getMainLooper()).post(new Runnable() {
       @Override
       public void run() {
           // things to do on the main thread
       }
   });

여기에는 활동 참조 또는 응용 프로그램 참조를 전달하지 않아도됩니다.

코 틀린 동등 물 :

    Handler(Looper.getMainLooper()).post(Runnable {
        // things to do on the main thread
    })

코 틀린 버전

당신이 활동에있는 다음 사용

runOnUiThread {
    //code that runs in main
}

당신이 활동 컨텍스트가 , mContext는 사용

mContext.runOnUiThread {
    //code that runs in main
}

사용 가능한 컨텍스트없는 곳에있는 경우

Handler(Looper.getMainLooper()).post {  
    //code that runs in main
}

내가 생각할 수있는 한 가지 방법은 다음과 같습니다.

1) UI가 서비스에 바인딩되도록하십시오.
2) 다음 Binder을 등록 하는 방법으로 다음과 같은 방법을 노출 하십시오 Handler.

public void registerHandler(Handler handler) {
    mHandler = handler;
}

3) UI 스레드에서 서비스에 바인딩 한 후 위의 메소드를 호출하십시오.

mBinder.registerHandler(new Handler());

4) 서비스 스레드에서 처리기를 사용하여 작업을 게시하십시오.

mHandler.post(runnable);

컨텍스트가없는 경우 가장 간단한 방법, RxAndroid를 사용하는 경우 다음을 수행 할 수 있습니다.

AndroidSchedulers.mainThread().scheduleDirect {
    runCodeHere()
}

핸들러를 사용하는보다 정확한 Kotlin 코드 :

Handler(Looper.getMainLooper()).post {  
 // your codes here run on main Thread
 }

HandlerThread 안드로이드에서 일반 자바 스레드에 대한 더 나은 옵션입니다.

  1. HandlerThread를 작성 하고 시작하십시오.
  2. 크리에이트 핸들러루퍼 HandlerThread에서를 :requestHandler
  3. postRunnable작업에requestHandler

UI 스레드와의 통신 HandlerThread

  1. 기본 스레드에 대한 Handlerwith Looper작성하고 메소드를 responseHandler대체하십시오.handleMessage
  2. 내부 Runnable(다른 스레드의 작업 HandlerThread이 경우), 전화 sendMessageresponseHandler
  3. sendMessage결과 호출은 handleMessage입니다 responseHandler.
  4. 속성을 가져 Message와서 처리하고 UI를 업데이트하십시오.

: TextView웹 서비스에서받은 데이터로 업데이트 합니다. 웹 서비스는 UI가 아닌 스레드에서 호출되어야하므로 HandlerThread네트워크 작업을 위해 생성 됩니다. 웹 서비스에서 컨텐츠를 가져 오면 메시지를 기본 스레드 (UI 스레드) 핸들러로 보내면 메시지를 Handler처리하고 UI를 업데이트합니다.

샘플 코드 :

HandlerThread handlerThread = new HandlerThread("NetworkOperation");
handlerThread.start();
Handler requestHandler = new Handler(handlerThread.getLooper());

final Handler responseHandler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message msg) {
        txtView.setText((String) msg.obj);
    }
};

Runnable myRunnable = new Runnable() {
    @Override
    public void run() {
        try {
            Log.d("Runnable", "Before IO call");
            URL page = new URL("http://www.your_web_site.com/fetchData.jsp");
            StringBuffer text = new StringBuffer();
            HttpURLConnection conn = (HttpURLConnection) page.openConnection();
            conn.connect();
            InputStreamReader in = new InputStreamReader((InputStream) conn.getContent());
            BufferedReader buff = new BufferedReader(in);
            String line;
            while ((line = buff.readLine()) != null) {
                text.append(line + "\n");
            }
            Log.d("Runnable", "After IO call:"+ text.toString());
            Message msg = new Message();
            msg.obj = text.toString();
            responseHandler.sendMessage(msg);


        } catch (Exception err) {
            err.printStackTrace();
        }
    }
};
requestHandler.post(myRunnable);

유용한 기사 :

핸들러 스레드-왜 당신은 안드로이드 앱에서 그들을 사용해야합니까?

안드로이드 루퍼 처리기 처리기


나는 이것이 오래된 질문이라는 것을 알고 있지만 Kotlin과 Java 모두에서 사용하는 메인 스레드 원 라이너를 발견했습니다. 이것은 서비스에 대한 최상의 솔루션은 아니지만 조각 내에서 UI를 변경하는 무언가를 호출하는 경우 매우 간단하고 명백합니다.

자바 (8) :

 getActivity().runOnUiThread(()->{
      //your main thread code
 });

코 틀린 :

this.runOnUiThread {
     //your main thread code
}

이 방법을 따르십시오. 이 방법을 사용하면 백그라운드 스레드에서 UI를 간단히 업데이트 할 수 있습니다. runOnUiThread는 메인 (UI) 스레드에서 작동합니다. 이 코드 스 니펫은 특히 초보자에게 덜 복잡하고 쉽다고 생각합니다.

AsyncTask.execute(new Runnable() {
            @Override
            public void run() {

            //code you want to run on the background
            someCode();

           //the code you want to run on main thread
 MainActivity.this.runOnUiThread(new Runnable() {

                    public void run() {

/*the code you want to run after the background operation otherwise they will executed earlier and give you an error*/
                        executeAfterOperation();

                   }
                });
            }
        });

서비스의 경우

oncreate에서 핸들러를 작성하십시오.

 handler = new Handler();

다음과 같이 사용하십시오

 private void runOnUiThread(Runnable runnable) {
        handler.post(runnable);
    }

public void mainWork() {
    new Handler(Looper.getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            //Add Your Code Here
        }
    });
}

이것은 문제가없는 서비스 클래스에서도 작동 할 수 있습니다.


Kotlin의 경우 Anko corountines를 사용할 수 있습니다 .

최신 정보

doAsync {
   ...
}

더 이상 사용되지 않음

async(UI) {
    // Code run on UI thread
    // Use ref() instead of this@MyActivity
}

Kotlin을 사용하면 모든 기능에서 다음과 같습니다.

runOnUiThread {
   // Do work..
}

참고 URL : https://stackoverflow.com/questions/11123621/running-code-in-main-thread-from-another-thread

반응형