다른 스레드의 메인 스레드에서 코드 실행
안드로이드 서비스에서 백그라운드 작업을 수행하기위한 스레드를 만들었습니다.
스레드가 기본 스레드의 메시지 대기열에 특정 작업을 게시 해야하는 상황이 있습니다 (예 : 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() {
});
이것이 당신이 찾고있는 것이기를 바랍니다.
컨텍스트에 액세스 할 수없는 경우 다른 간단한 방법이 있습니다.
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
안드로이드에서 일반 자바 스레드에 대한 더 나은 옵션입니다.
- HandlerThread를 작성 하고 시작하십시오.
- 크리에이트 핸들러 와 루퍼 HandlerThread에서를 :
requestHandler
post
Runnable
작업에requestHandler
UI 스레드와의 통신 HandlerThread
- 기본 스레드에 대한
Handler
withLooper
를 작성하고 메소드를responseHandler
대체하십시오.handleMessage
- 내부
Runnable
(다른 스레드의 작업HandlerThread
이 경우), 전화sendMessage
에responseHandler
- 의
sendMessage
결과 호출은handleMessage
입니다responseHandler
. - 속성을 가져
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
'Programing' 카테고리의 다른 글
byte []를 Java로 파일로 (0) | 2020.03.17 |
---|---|
MySQL에서 --secure-file-priv를 어떻게 해결해야합니까? (0) | 2020.03.17 |
Bash의 파일에서 마지막 줄을 제거하십시오. (0) | 2020.03.17 |
"이 응용 프로그램은 백그라운드 스레드에서 자동 레이아웃 엔진을 수정하고 있습니다"오류가 발생합니까? (0) | 2020.03.17 |
htaccess는 https : // www로 리디렉션 (0) | 2020.03.17 |