Android 에서 okhttp 3 사용 에 대한 자세 한 설명
프로젝트 모듈 의 build.gradle 에 okhttp 3 의존 도 를 추가 합 니 다.
compile 'com.squareup.okhttp3:okhttp:3.3.1'
기본 사용1.okhttp 3 Get 방법
1.1,okhttp 3 동기 화 Get 방법
/**
* Get
*/
private void okHttp_synchronousGet() {
new Thread(new Runnable() {
@Override
public void run() {
try {
String url = "https://api.github.com/";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
okhttp3.Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
Log.i(TAG, response.body().string());
} else {
Log.i(TAG, "okHttp is request error");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
Request 는 okhttp 3 의 요청 대상 이 고 Response 는 okhttp 3 의 응답 입 니 다.response.isSuccessful()을 통 해 요청 이 성 공 했 는 지 판단 합 니 다.
@Contract(pure=true)
public boolean isSuccessful()
Returns true if the code is in [200..300), which means the request was successfully received, understood, and accepted.
되 돌아 오 는 데 이 터 를 가 져 옵 니 다.response.body().string()을 통 해 가 져 올 수 있 습 니 다.기본 값 은 utf-8 형식 입 니 다.string()은 작은 데이터 정 보 를 가 져 오 는 데 적 용 됩 니 다.되 돌아 오 는 데이터 가 1M 를 초과 하면 stream()을 사용 하여 되 돌아 오 는 데 이 터 를 가 져 오 는 것 을 권장 합 니 다.string()방법 은 전체 문 서 를 메모리 에 불 러 오기 때 문 입 니 다.
@NotNull
public final java.lang.String string()
throws java.io.IOException
Returns the response as a string decoded with the charset of the Content-Type header. If that header is either absent or lacks a charset, this will attempt to decode the response body as UTF-8.
Throws:
java.io.IOException
물론 스 트림 출력 형식 도 가 져 올 수 있 습 니 다.
public final java.io.InputStream byteStream()
1.2,okhttp 3 비동기 Get 방법가끔 은 파일(예 를 들 어 네트워크 그림)을 다운로드 해 야 합 니 다.만약 에 파일 이 비교적 크 면 전체 다운로드 에 시간 이 걸 립 니 다.보통 우 리 는 시간 이 걸 리 는 작업 스 레 드 에 작업 을 넣 고 okhttp 3 비동기 방법 을 사용 합 니 다.우 리 는 작업 스 레 드 를 열 어 네트워크 요청 을 수행 하지 않 아 도 되 고 돌아 오 는 결과 도 작업 스 레 드 에 있 습 니 다.
/**
* Get
*/
private void okHttp_asynchronousGet(){
try {
Log.i(TAG,"main thread id is "+Thread.currentThread().getId());
String url = "https://api.github.com/";
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(new okhttp3.Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
}
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
// : ,
Log.i(TAG,"callback thread id is "+Thread.currentThread().getId());
Log.i(TAG,response.body().string());
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
주:Android 4.0 이후 네트워크 요청 은 작업 스 레 드 에서 실행 되 어야 하 며 주 스 레 드 에서 실행 할 수 없습니다.따라서 okhttp 3 의 동기 화 Get 방법 을 사용 하려 면 새로운 작업 스 레 드 호출 이 필요 합 니 다.1.3.요청 헤더 추가
okhttp 3 요청 헤 더 를 추가 하려 면 Request.Builder()에서.header(String key,String value)또는.addHeader(String key,String value)를 사용 해 야 합 니 다.
.header(String key,String value)를 사용 합 니 다.key 가 존재 하면 해당 key 에 대응 하 는 value 를 제거 하고 새 value 를 추가 합 니 다.즉,원래 value 를 교체 합 니 다.
.addHeader(String key,String value)를 사용 합 니 다.현재 값 이 존재 하 더 라 도 새 value 값 만 추가 하고 원래 값 을 제거/교체 하지 않 습 니 다.
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
Request request = new Request.Builder()
.url("https://api.github.com/repos/square/okhttp/issues")
.header("User-Agent", "OkHttp Headers.java")
.addHeader("Accept", "application/json; q=0.5")
.addHeader("Accept", "application/vnd.github.v3+json")
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println("Server: " + response.header("Server"));
System.out.println("Date: " + response.header("Date"));
System.out.println("Vary: " + response.headers("Vary"));
}
2、okhttp 3 Post 방법2.1,Post 제출 키 쌍
많은 경우,우 리 는 Post 방식 을 통 해 키 값 을 서버 에 전송 해 야 합 니 다.okhttp 3 는 FormBody.Builder 를 사용 하여 요청 한 매개 변수 키 값 쌍 을 만 듭 니 다.
private void okHttp_postFromParameters() {
new Thread(new Runnable() {
@Override
public void run() {
try {
// url:http://api.k780.com:88/?app=weather.future&weaid=1&&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json
String url = "http://api.k780.com:88/";
OkHttpClient okHttpClient = new OkHttpClient();
String json = "{'app':'weather.future','weaid':'1','appkey':'10003'," +
"'sign':'b59bc3ef6191eb9f747dd4e83c99f2a4','format':'json'}";
RequestBody formBody = new FormBody.Builder().add("app", "weather.future")
.add("weaid", "1").add("appkey", "10003").add("sign",
"b59bc3ef6191eb9f747dd4e83c99f2a4").add("format", "json")
.build();
Request request = new Request.Builder().url(url).post(formBody).build();
okhttp3.Response response = okHttpClient.newCall(request).execute();
Log.i(TAG, response.body().string());
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
2.2 、Post a StringPost 방법 으로 문자열 을 보 낼 수 있 지만 1M 이상 의 텍스트 정 보 를 보 내 는 것 은 권장 되 지 않 습 니 다.다음 예제 에 서 는 markdown 텍스트 를 보 냅 니 다.
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("text/x-markdown; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
String postBody = ""
+ "Releases
"
+ "--------
"
+ "
"
+ " * _1.0_ May 6, 2013
"
+ " * _1.1_ June 15, 2013
"
+ " * _1.2_ August 11, 2013
";
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, postBody))
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
2.3 、Post Streamingpost 는 stream 대상 을 요청 체 로 할 수 있 으 며,Okio 로 데 이 터 를 출력 스 트림 형식 으로 쓸 수 있 습 니 다.
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("text/x-markdown; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
RequestBody requestBody = new RequestBody() {
@Override public MediaType contentType() {
return MEDIA_TYPE_MARKDOWN;
}
@Override public void writeTo(BufferedSink sink) throws IOException {
sink.writeUtf8("Numbers
");
sink.writeUtf8("-------
");
for (int i = 2; i <= 997; i++) {
sink.writeUtf8(String.format(" * %s = %s
", i, factor(i)));
}
}
private String factor(int n) {
for (int i = 2; i < n; i++) {
int x = n / i;
if (x * i == n) return factor(x) + " × " + i;
}
return Integer.toString(n);
}
};
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(requestBody)
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
2.4 、Post file
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("text/x-markdown; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
File file = new File("README.md");
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
3.기타 설정3.1,Gson 해석 Response 의 Gson 대상
Response 대상 의 내용 이 json 문자열 이 라면 Gson 을 사용 하여 문자열 을 대상 으로 포맷 할 수 있 습 니 다.Response Body.charStream()은 응답 헤더 에 있 는 Content-Type 을 Response 로 데 이 터 를 되 돌려 주 는 인 코딩 방식 으로 사용 합 니 다.기본 값 은 UTF-8 입 니 다.
private final OkHttpClient client = new OkHttpClient();
private final Gson gson = new Gson();
public void run() throws Exception {
Request request = new Request.Builder()
.url("https://api.github.com/gists/c2a7c39532239ff261be")
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
Gist gist = gson.fromJson(response.body().charStream(), Gist.class);
for (Map.Entry<String, GistFile> entry : gist.files.entrySet()) {
System.out.println(entry.getKey());
System.out.println(entry.getValue().content);
}
}
static class Gist {
Map<String, GistFile> files;
}
static class GistFile {
String content;
}
3.2,okhttp 3 로 컬 캐 시okhttp 프레임 워 크 전역 에 OkHttpClient 인 스 턴 스(new OkHttpClient()만 있어 야 하 며,인 스 턴 스 를 처음 만 들 때 캐 시 경로 와 크기 를 설정 해 야 합 니 다.설 정 된 캐 시 만 있 으 면 okhttp 기본 값 은 캐 시 기능 을 자동 으로 사용 합 니 다.
package com.jackchan.test.okhttptest;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import com.squareup.okhttp.Cache;
import com.squareup.okhttp.CacheControl;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import java.io.File;
import java.io.IOException;
public class TestActivity extends ActionBarActivity {
private final static String TAG = "TestActivity";
private final OkHttpClient client = new OkHttpClient();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
File sdcache = getExternalCacheDir();
int cacheSize = 10 * 1024 * 1024; // 10 MiB
client.setCache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
new Thread(new Runnable() {
@Override
public void run() {
try {
execute();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
public void execute() throws Exception {
Request request = new Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build();
Response response1 = client.newCall(request).execute();
if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1);
String response1Body = response1.body().string();
System.out.println("Response 1 response: " + response1);
System.out.println("Response 1 cache response: " + response1.cacheResponse());
System.out.println("Response 1 network response: " + response1.networkResponse());
Response response2 = client.newCall(request).execute();
if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2);
String response2Body = response2.body().string();
System.out.println("Response 2 response: " + response2);
System.out.println("Response 2 cache response: " + response2.cacheResponse());
System.out.println("Response 2 network response: " + response2.networkResponse());
System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body));
}
}
okhttpclient 는 응용 프로그램의 개념 과 같 습 니 다.전체 okhttp 의 큰 기능 을 총괄 하고 있 습 니 다.이 를 통 해 캐 시 디 렉 터 리 를 설정 하고 위의 코드 를 실행 하여 얻 은 결 과 는 다음 과 같 습 니 다.response 1 의 결 과 는 network response 에 있 습 니 다.네트워크 요청 에서 불 러 온 것 을 의미 합 니 다.response 2 의 network response 는 null 이 고 cacheresponse 는 데이터 가 있 습 니 다.캐 시 를 설 정 했 기 때문에 두 번 째 요청 에서 캐 시 에 있 으 면 네트워크 요청 을 하지 않 습 니 다.
그러나 가끔 은 캐 시 가 있 는 상황 에서 도 배경 으로 최신 자원(예 를 들 어 자원 업데이트)을 요청 해 야 할 때 네트워크 데 이 터 를 요청 해 야 한다 고 요구 할 수 있 습 니 다.
public void execute() throws Exception {
Request request = new Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build();
Response response1 = client.newCall(request).execute();
if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1);
String response1Body = response1.body().string();
System.out.println("Response 1 response: " + response1);
System.out.println("Response 1 cache response: " + response1.cacheResponse());
System.out.println("Response 1 network response: " + response1.networkResponse());
request = request.newBuilder().cacheControl(CacheControl.FORCE_NETWORK).build();
Response response2 = client.newCall(request).execute();
if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2);
String response2Body = response2.body().string();
System.out.println("Response 2 response: " + response2);
System.out.println("Response 2 cache response: " + response2.cacheResponse());
System.out.println("Response 2 network response: " + response2.networkResponse());
System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body));
}
위의 코드 중response 2 대응 하 는 request 가
request = request.newBuilder().cacheControl(CacheControl.FORCE_NETWORK).build();
운행 결 과 를 봅 시다.
response 2 의 cache response 는 null 이 고 network response 는 여전히 데이터 가 있 습 니 다.
같은 우 리 는 FORCE 를 사용 할 수 있다.CACHE 는 캐 시 된 데 이 터 를 사용 하도록 강제 하지만,요청 할 경우 네트워크 에서 가 져 와 야 데이터 가 나 오지 만 FORCE 를 사용 합 니 다.CACHE 정책 은 504 오 류 를 되 돌려 줍 니 다.코드 는 다음 과 같 습 니 다.okhttpclient 의 캐 시 에 가서 request 를 FORCE 로 설정 합 니 다.CACHE
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
File sdcache = getExternalCacheDir();
int cacheSize = 10 * 1024 * 1024; // 10 MiB
//client.setCache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
new Thread(new Runnable() {
@Override
public void run() {
try {
execute();
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage().toString());
}
}
}).start();
}
public void execute() throws Exception {
Request request = new Request.Builder()
.url("http://publicobject.com/helloworld.txt")
.build();
Response response1 = client.newCall(request).execute();
if (!response1.isSuccessful()) throw new IOException("Unexpected code " + response1);
String response1Body = response1.body().string();
System.out.println("Response 1 response: " + response1);
System.out.println("Response 1 cache response: " + response1.cacheResponse());
System.out.println("Response 1 network response: " + response1.networkResponse());
request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build();
Response response2 = client.newCall(request).execute();
if (!response2.isSuccessful()) throw new IOException("Unexpected code " + response2);
String response2Body = response2.body().string();
System.out.println("Response 2 response: " + response2);
System.out.println("Response 2 cache response: " + response2.cacheResponse());
System.out.println("Response 2 network response: " + response2.networkResponse());
System.out.println("Response 2 equals Response 1? " + response1Body.equals(response2Body));
}
3.3、okhttp 3 취소 요청
okhttp 3 네트워크 요청 이 더 이상 필요 하지 않 으 면,준비 중인 동기 화/비동기 요청 을 종료 하기 위해 Call.cancel()을 사용 할 수 있 습 니 다.요청 을 쓰 거나 되 돌아 오 는 response 를 읽 고 있 는 스 레 드 가 있 으 면 IOException 을 받 습 니 다.
private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
Request request = new Request.Builder()
.url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay.
.build();
final long startNanos = System.nanoTime();
final Call call = client.newCall(request);
// Schedule a job to cancel the call in 1 second.
executor.schedule(new Runnable() {
@Override public void run() {
System.out.printf("%.2f Canceling call.%n", (System.nanoTime() - startNanos) / 1e9f);
call.cancel();
System.out.printf("%.2f Canceled call.%n", (System.nanoTime() - startNanos) / 1e9f);
}
}, 1, TimeUnit.SECONDS);
try {
System.out.printf("%.2f Executing call.%n", (System.nanoTime() - startNanos) / 1e9f);
Response response = call.execute();
System.out.printf("%.2f Call was expected to fail, but completed: %s%n",
(System.nanoTime() - startNanos) / 1e9f, response);
} catch (IOException e) {
System.out.printf("%.2f Call failed as expected: %s%n",
(System.nanoTime() - startNanos) / 1e9f, e);
}
}
3.4、okhttp 3 시간 초과 설정okhttp 3 는 연결 시간 초과,읽 기와 쓰기 시간 초과 설정 을 지원 합 니 다.
private final OkHttpClient client;
public ConfigureTimeouts() throws Exception {
client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
}
public void run() throws Exception {
Request request = new Request.Builder()
.url("http://httpbin.org/delay/2") // This URL is served with a 2 second delay.
.build();
Response response = client.newCall(request).execute();
System.out.println("Response completed: " + response);
}
3.5,okhttp 3 재 활용 okhttpclient 설정모든 HTTP 가 요청 한 프 록 시 설정,시간 초과,캐 시 설정 등 은 OkHttpClient 에 설정 해 야 합 니 다.요청 한 설정 을 변경 하려 면 OkHttpClient.newBuilder()를 사용 하여 builder 대상 을 가 져 올 수 있 습 니 다.이 builder 대상 은 원래 OkHttpClient 와 같은 연결 풀,설정 등 을 공유 합 니 다.
다음 예제 에서'OkHttpClient'설정 2 개 를 복사 한 다음 에 각각 시간 초과 시간 을 설정 합 니 다.
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
Request request = new Request.Builder()
.url("http://httpbin.org/delay/1") // This URL is served with a 1 second delay.
.build();
try {
// Copy to customize OkHttp for this request.
OkHttpClient copy = client.newBuilder()
.readTimeout(500, TimeUnit.MILLISECONDS)
.build();
Response response = copy.newCall(request).execute();
System.out.println("Response 1 succeeded: " + response);
} catch (IOException e) {
System.out.println("Response 1 failed: " + e);
}
try {
// Copy to customize OkHttp for this request.
OkHttpClient copy = client.newBuilder()
.readTimeout(3000, TimeUnit.MILLISECONDS)
.build();
Response response = copy.newCall(request).execute();
System.out.println("Response 2 succeeded: " + response);
} catch (IOException e) {
System.out.println("Response 2 failed: " + e);
}
}
3.6、okhttp 3 처리 검증okhttp 3 은 인증 되 지 않 은 요청 을 자동 으로 다시 시도 합 니 다.401 Not Authorized 를 되 돌려 달라 고 요청 할 때 Anthenticator 를 제공 해 야 합 니 다.
private final OkHttpClient client;
public Authenticate() {
client = new OkHttpClient.Builder()
.authenticator(new Authenticator() {
@Override public Request authenticate(Route route, Response response) throws IOException {
System.out.println("Authenticating for response: " + response);
System.out.println("Challenges: " + response.challenges());
String credential = Credentials.basic("jesse", "password1");
return response.request().newBuilder()
.header("Authorization", credential)
.build();
}
})
.build();
}
public void run() throws Exception {
Request request = new Request.Builder()
.url("http://publicobject.com/secrets/hellosecret.txt")
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.