Android 에서 OkHttp 3 의 예 와 하위 스 레 드 에서 UI 스 레 드 를 업데이트 하 는 방법 을 자세히 알 아 봅 니 다.
우선 좀 알 아야 합 니 다.여기 서 말 하 는 UI 스 레 드 와 메 인 스 레 드 는 같은 것 입 니 다.UI 를 업데이트 할 수 있 는 유일한 스 레 드 입 니 다.이 건 그냥 점 이에 요.그리고 이 내용 자 체 는 일상적인 개발 에 도 자주 사용 되 므 로 잘 배 워 볼 만하 다.
okHttp 동기 화 요청
첫 번 째 열 은 동기 화 요청 의 예 입 니 다.
private void performSyncHttpRequest() {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.baidu.com")
.build();
Call call = client.newCall(request);
Response response = call.execute();
}
그러나 이러한 안 드 로 이 드 의 메 인 스 레 드 에서 네트워크 요청 을 직접 호출 하 는 방법 은 통 하지 않 습 니 다.UI Thread 요청 네트워크 의 이상 을 직접 던 집 니 다.그래서 우 리 는 숨 길 수 있 도록 약간의 변경 을 해 야 한다.요청 을 동기 화 요청 방식 으로 쓰 지만 워 커 스 레 드 에 두 고 이 동작 을 수행 합 니 다.
private Handler requestHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case REQUEST_SUCCESS:
Toast.makeText(MainActivity.this, "SUCCESSFUL", Toast.LENGTH_SHORT).show();
break;
case REQUEST_FAIL:
Toast.makeText(MainActivity.this, "request failed", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
};
private void performSyncHttpRequest() {
Runnable requestTask = new Runnable() {
@Override
public void run() {
Message msg = requestHandler.obtainMessage();
try {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.baidu.com")
.build();
Call call = client.newCall(request);
// 1
Response response = call.execute();
if (!response.isSuccessful()) {
msg.what = REQUEST_FAIL;
} else {
msg.what = REQUEST_SUCCESS;
}
} catch (IOException ex) {
msg.what = REQUEST_FAIL;
} finally {
// send the message
// 2
msg.sendToTarget();
}
}
};
Thread requestThread = new Thread(requestTask);
requestThread.start();
}
그래서 동기 화 요청 은 모두 이렇게 합 니 다.Response response=call.execute().1.동기 화 요청 을 시작 하기 전에 OkHttpClient 를 새로 초기 화 합 니 다.그리고 구체 적 인 요청 입 니 다.요청 builder 로 이 Request 를 만 듭 니 다.저희 가 여기 서 간단 한 url 을 위해 서 는 바로*입 니 다.http://www.baidu.com*됐어 요.다음은 앞에서 초기 화 된 client 로 call:Call call=client.newCall(request)를 시작 합 니 다.마지막 으로 이 call:Response response=call.execute()를 실행 합 니 다.요청 한 response 를 받 습 니 다.
2.이 부분 은 당분간 관심 을 갖 지 않 아 도 된다.이 예 는 okHttp 가 동기 화 요청 을 하 는 방법 을 실행 하 는 방식 으로 보 여주 기 위 한 것 이기 때문이다.
okHttp 비동기 요청
안 드 로 이 드 자체 가 동기 화 요청 을 지원 하지 않 는 이상 동기 화 요청 을 할 사람 도 없습니다.이렇게 하면 심각 한 사용자 체험 문 제 를 초래 할 수 있다.만약 당신 이 폭포 류 를 가지 고 있다 면 폭포 류 에 모두 그림 이 표 시 될 것 이 라 고 상상 해 보 세 요.현재 사용 자 는 폭포 흐름 의 그림 을 끊임없이 내 려 다 보아 야 한다.이 그림 들 이 모두 동기 화 요청 을 한다 면 언제 한 페이지 를 넘 길 수 있 는 지 시스템 의 ANR 은 이미 튀 어 나 왔 다.
그래서 우 리 는 어떻게 비동기 적 인 요 구 를 하 는 지 탐구 해 보 자.
private void performAsyncHttpRequest() {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.baidu.com")
.build();
Call call = client.newCall(request);
// 1
call.enqueue(new Callback() {
// 2
@Override
public void onFailure(Call call, IOException e) {
//Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
Log.d(TAG, "Main Thread");
} else {
Log.d(TAG, "Not Main Thread");
}
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
// 3
if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
Log.d(TAG, "Main Thread");
} else {
Log.d(TAG, "Not Main Thread");
}
}
});
}
1.동기 화 요청 은 execute 방법 을 사용 하고,비동기 화 는 call.enqueue(new Callback()방법 을 사용 합 니 다.2.이 Callback 인 터 페 이 스 는 두 가지 방법 을 제공 합 니 다.하 나 는 onFailure 이 고 하 나 는 onResponse 입 니 다.이 두 가지 방법 은 요청 이 실 패 했 을 때 와 성공 할 때 각각 호출 된다.
3.원래 모든 것 이 쉬 울 것 같 았 다.네트워크 요청 이 성공 하거나 실 패 했 습 니 다.인터페이스 에서 직접 업 데 이 트 했 습 니 다.하지만 나 무 는 이렇게 하면 이상 하 게 던 질 줄 알 았 다.그리고 보 니 onFailure 와 onResponse 두 가지 방법 이 메 인 스 레 드 에서 실행 되 는 것 이 아니 었 습 니 다.인쇄 된 log 는 okhttp.demo.com.okhttpdemo D/\#\#okHttp:Not Main Thread 입 니 다.
그래서 메 인 스 레 드 에서 view 를 업데이트 하려 면 다른 방법 을 생각해 야 합 니 다.워 커 스 레 드 에서 메 인 스 레 드 를 업데이트 하면 이상 합 니 다.일반적으로 하위 스 레 드 에서 view 를 업데이트 하 는 몇 가지 방법 이 있 습 니 다.
하위 스 레 드 에서 UI 스 레 드 업데이트
1.Activity 의 runOnUiThread 방법
Activity 에 서 는 runOnUiThread 라 는 방법 이 있 습 니 다.이 방법 은 Runnable 인 스 턴 스 를 매개 변수 로 해 야 합 니 다.
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "code: ");
Toast.makeText(MainActivity.this, String.valueOf(response.code()), Toast.LENGTH_SHORT).show();
}
});
2.View 의 post 방법View 의 post 방법 도 마찬가지 입 니 다.Runnable 의 인 스 턴 스 를 던 져 넣 습 니 다.그리고 메 인 스 레 드 에서 실 행 했 습 니 다.Toast 는 그 럴 방법 이 없 을 거 야.
MainActivity.this.mView.post(new Runnable() {
public void run() {
Log.d("UI thread", "I am the UI thread");
}
});
기타1.Handler 를 사용 합 니 다.이 앞의 okHttp 동기 화 요청 의 예 를 사용 할 수 있 습 니 다.
2.AsyncTask,메 인 스 레 드 에서 실행 할 수 있 는 두 가지 방법 이 있 습 니 다:onProgressUpdate 와 onPost Execute.여기 서 우 리 는 진 도 를 갱신 하려 는 것 이 아니 기 때문에 다음 방법 을 고려 하 는 것 이다.
private class BackgroundTask extends AsyncTask<String, Void, Bitmap> {
protected void onPostExecute(Bitmap result) {
Log.d("UI thread", "I am the UI thread");
}
}
이상 을 종합해 보면 UI 스 레 드 를 업데이트 하 는 방법 에서 마지막 으로 말 한 Handler 방법 과 AsyncTask 가 너무 무겁다.특히 AsyncTask.한 무더기 의 방법 을 계승 해 야 목적 을 달성 할 수 있 고 우리 가 사용 해 야 할 okHttp 의 사용 방법 과 호 환 되 지 않 는 부분 이 많다.그래서 우 리 는 앞의 두 가지 만 생각한다.하지만 두 가지 방법 은 다르다.물론 방법의 이름 이 다르다 는 것 은 아니다.안 드 로 이 드 의 소스 코드 를 살 펴 보 자.이 두 가지 방법 이 어떻게 실현 되 었 는 지.
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
// mHandler.post(action); post
public final boolean post(Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
방법 runOnUiThread 는 마지막 으로 Handler 의 sendmessageDelayed 를 호출 합 니 다.근 데 여 기 는 0 밖 에 안 됐어 요.즉,방법 이 여기에 전 달 될 때 runOnUiThread 의 인자 Runnable 인 스 턴 스 를 즉시 실행 합 니 다.다음은 View 의 post 방법 을 살 펴 보 겠 습 니 다.
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);
return true;
}
보통 ViewRootImpl.getRunQueue().post(action)를 실행 합 니 다.즉,Runnable 의 인 스 턴 스 는 이벤트 대기 열 에 만 추가 되 어 순서대로 실 행 됩 니 다.반드시 즉각 집행 되 는 것 은 아니다.우 리 는 그렇게 많은 것 을 연 구 했 는데 마지막 으로 runOnUi Thread 를 사용 하여 인터페이스 를 업데이트 하 는 것 이 바로 방법 이다.
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
final String errorMMessage = e.getMessage();
if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
Log.d(TAG, "Main Thread");
} else {
Log.d(TAG, "Not Main Thread");
}
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, errorMMessage, Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
Log.d(TAG, "Main Thread");
} else {
Log.d(TAG, "Not Main Thread");
}
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "code: ");
Toast.makeText(MainActivity.this, String.valueOf(response.code()), Toast.LENGTH_SHORT).show();
}
});
}
});
요청 이 성공 하 든 실패 하 든 Toast 를 팝 업 합 니 다.UI 스 레 드 에서 이 Toast 를 MainActivity.this.runOnUiThread 로 팝 업 합 니 다.이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
안 드 로 이 드 에서 UI 를 비동기 로 업데이트 하 는 네 가지 방식성능 요구 로 인해 Android 는 UI 스 레 드 에서 만 UI 를 업데이트 해 야 한 다 는 것 을 잘 알 고 있 습 니 다.다른 스 레 드 에서 UI 를 업데이트 하려 면 저 는 대체적으로 4 가지 방식 을 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.