OkHttp3 시작 안내

판권 소유, 전재는 출처를 밝혀 주십시오:linzhiyonghttps://blog.csdn.net/u012527802/article/details/81013772 https://www.jianshu.com/p/af144d662bfd
기사 1, OkHttp3 시작 설명:https://www.jianshu.com/p/af144d662bfd2. OkHttp3 시작하여 설명하는 쿠키 지속성:https://www.jianshu.com/p/23b35d403148
OkHttp는 네트워크 요청을 처리하는 소스 오픈 프로젝트로 안드로이드에서 가장 핫한 경량급 프레임워크로 본고는 주로 OkHttp3의 기본적인 사용 방법을 소개한다.홈페이지:http://square.github.io/okhttp/ Github:https://github.com/square/okhttpOkHttp3Demo 전송문:https://github.com/linzhiyong/OkHttp3Demo서버 데모 전송문:https://github.com/linzhiyong/SpringMVCDemo
자신의 프로젝트 경험과 결합하여 주로 다음과 같은 몇 가지 측면에서 소개한다.
OkHttp3 시작 안내
  • OkHttp3 시작 안내
  • 개발 구성
  • OkHttpClient 기본 매개변수 소개
  • 일반 GET 요청(동기식/비동기식)
  • 일반 POST 요청(동기식/비동기식)
  • tag에 따라 요청 취소
  • POST 요청 제출 String
  • POST 요청 커뮤니케이션
  • POST 요청 제출JSON(실체전JSON)
  • POST 요청 일반 Form 양식
  • POST 요청 혼합 Form 양식 제출
  • POST 요청 제출 양식/다중 파일(진행률 표시줄)
  • 1. 진행률 표시줄 없이 단일 파일 제출
  • 2. 다중 파일 제출(진행률 표시줄 없음)
  • 3. 제출서 파일(!!!진행률 표시줄!!!)


  • GET 요청 파일 다운로드(진행률 막대 포함)
  • 1. 파일 다운로드(진행률 표시줄 없음)
  • 2. 파일 다운로드(!!!진행률 표시줄!!!)





  • 개발 구성
    AndroidStudio에서 개발한 app의build.gradle 파일에 okhttp3에 대한 의존도 증가:
    dependencies {
        implementation 'com.squareup.okhttp3:okhttp:3.10.0'
    }

    네트워크 요청에는 네트워크 권한이 필요합니다. AndroidManifest에 있어야 합니다.xml 구성:
    <uses-permission android:name="android.permission.INTERNET" />

    OkHttpClient 기본 매개변수 소개
    OkHttpClient는 OkHttpClient를 통과합니다.Builder에서 매개변수를 구성합니다. 기본 매개변수는 다음과 같습니다.
    OkHttpClient.Builder builder = new OkHttpClient.Builder()
                        .readTimeout(HTTP_TIME_OUT, TimeUnit.SECONDS)
                        .writeTimeout(HTTP_TIME_OUT, TimeUnit.SECONDS)
                        .connectTimeout(HTTP_TIME_OUT, TimeUnit.SECONDS)
                        );
    OkHttpClient okHttpClient = okHttpClient = builder.build();

    쿠키 유지, Https 인증서 설정, Interceptor 차단기 설정 등 다른 매개변수에 대해서는 다음 장에서 설명합니다.
    주: 1. 프로젝트에서 OkHttpClient 실례를 만들고 다시 사용하는 것을 권장합니다. 이것은 모든 실례가 자신의 연결 탱크와 스레드 탱크를 가지고 있기 때문입니다. 연결 탱크와 스레드 탱크를 다시 사용하면 지연을 줄이고 메모리를 절약할 수 있습니다.2. 이 예에서 나는 OkHttpClient 실례를 LOkHttp3Utils에 봉하고 LOkHttp3Utils를 사용한다.okHttpClient()를 가져옵니다.
    일반 GET 요청(동기식/비동기식)
    //      
    Request request = new Request.Builder()
                    .url(url) //     
                    .get() // get  
                    .addHeader("name", "value") //      
                    .tag("getSync") //    request    tag,  okHttpClient   tag       
                    .build();
    Call call = LOkHttp3Utils.okHttpClient().newCall(request);
    //     
    Response response = call.execute();
    
    //     
    call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    Log.i("", "");
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    int code = response.code();
                    if (code == 200) {
                        String result = response.body().string();
                        Log.i("r", result);
                    }
                    else {
                        Log.e("e", response.message());
                    }
                }
    });

    주: 1. 콜 대상은 요청 집행자로서 요청을 취소할 수 있고 콜 요청은 한 번만 실행할 수 있다.2. Response는 응답체로서 되돌아오는 string을 가져오려면response를 사용합니다.body().string (), 되돌아오는 바이트를 가져오려면response를 사용하십시오.body().bytes (), 되돌아오는 바이트 흐름 (다운로드 파일) 을 가져오려면response를 사용하십시오.body().byteStream();
    일반 POST 요청(동기식/비동기식)
    //     body,MediaType      
    RequestBody requestBody = RequestBody.create(MediaType.parse("text/html; charset=utf-8"), content);
    //      
    Request request = new Request.Builder()
            .url(url)
            .post(requestBody)
            .addHeader("name", "value")
            .tag("postSync")
            .build();
    Call call = LOkHttp3Utils.okHttpClient().newCall(request);
    //     
    Response response = call.execute();
    
    //     
    call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    Log.i("", "");
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    int code = response.code();
                    if (code == 200) {
                        String result = response.body().string();
                        Log.i("r", result);
                    }
                    else {
                        Log.e("e", response.message());
                    }
                }
    });

    주: RequestBody는 요청 제출의 패키지로서 다양한 실현 형식이 있습니다.FormBody,MultipartBody,string,file,stream,form을 제출하는 캐리어입니다.
    tag에서 요청 취소
    요청 Request를 만들 때 tag 속성이 추가된 경우 tag를 통해 요청을 취소할 수 있습니다.
    /**
     *   Tag    
     *
     * @param client OkHttpClient
     * @param tag tag
     */
    public static void cancelTag(OkHttpClient client, Object tag) {
        if (client == null || tag == null) return;
        for (Call call : client.dispatcher().queuedCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }
        for (Call call : client.dispatcher().runningCalls()) {
            if (tag.equals(call.request().tag())) {
                call.cancel();
            }
        }
    }
    
    /**
     *         
     *
     * @param client OkHttpClient
     */
    public static void cancelAll(OkHttpClient client) {
        if (client == null) return;
        for (Call call : client.dispatcher().queuedCalls()) {
            call.cancel();
        }
        for (Call call : client.dispatcher().runningCalls()) {
            call.cancel();
        }
    }

    주: 중복된 코드의 양을 줄이기 위해 다음에string, json, file 제출에 관한 방법은 RequestBody를 어떻게 만드는지 적고 후속 Request,Call, 동기화 비동기 호출은 중복 나열에 없습니다.
    POST 요청 제출 String
    //        
    String content = "     ";
    RequestBody requestBody = RequestBody.create(MediaType.parse("text/html; charset=utf-8"), content);

    POST 요청 커뮤니케이션
    RequestBody requestBody = new RequestBody() {
        @Override
        public MediaType contentType() {
            return MediaType.parse("application/octet-stream; charset=utf-8");
        }
    
        @Override
        public void writeTo(BufferedSink sink) throws IOException {
            sink.writeUtf8("        ");
            //                 
        }
    };

    POST 요청 제출 JSON(개체 이전 JSON)
    //   JSON
    String bodyStr = "json";
    RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), bodyStr);

    POST 요청 일반 Form 양식 제출
    FormBody formBody = new FormBody.Builder()
            .add("key1", "value1")
            .add("key2", "value2")
            .add("key3", "value3")
            .build();

    POST에서 혼합 Form 양식 제출 요청(텍스트 매개 변수 + 파일)
    File file = new File("filePath");
    RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream; charset=utf-8"), file);
    
    //    
    RequestBody requestBody = new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("key1", "value1")
            .addFormDataPart("key2", "value2")
            .addFormDataPart("key3", "value3")
            .addFormDataPart("file1", "name1", fileBody)
            .build();
    
    //    
    FormBody formBody = new FormBody.Builder()
            .add("key1", "value1")
            .add("key2", "value2")
            .add("key3", "value3")
            .build();
    RequestBody requestBody1 = new MultipartBody.Builder()
            .addPart(Headers.of(
                    "Content-Disposition",
                    "form-data; name=\"params\""),
                    formBody)
            .addPart(Headers.of(
                    "Content-Disposition",
                    "form-data; name=\"file\"; filename=\"plans.xml\""),
                    fileBody)
            .build();

    POST 요청 제출 양식/다중 파일(진행률 표시줄)
    1. 진행률 표시줄 없이 단일 파일 제출
    File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "test.txt");
    RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
    
    //    
    RequestBody requestBody = new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("file1", file.getName(), fileBody)
            .build();
    
    //    
    RequestBody requestBody1 = new MultipartBody.Builder()
            .addPart(Headers.of(
                    "Content-Disposition",
                    "form-data; name=\"file1\"; filename=\"" + file.getName() + "\""),
                    fileBody)
            .build();

    2. 진행률 막대 없이 여러 파일 제출
    File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "test.txt");
    RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
    RequestBody fileBody2 = RequestBody.create(MediaType.parse("application/octet-stream"), file);
    
    //    
    RequestBody requestBody = new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("file1", file.getName(), fileBody)
            .addFormDataPart("file2", file.getName(), fileBody2)
            .build();
    
    //    
    RequestBody requestBody1 = new MultipartBody.Builder()
            .addPart(Headers.of(
                    "Content-Disposition",
                    "form-data; name=\"file1\"; filename=\"" + file.getName() + "\""),
                    fileBody)
            .addPart(Headers.of(
                    "Content-Disposition",
                    "form-data; name=\"file2\"; filename=\"" + file.getName() + "\""),
                    fileBody2)
            .build();

    3. 서류 제출(!!!진도표 달기!!!)
    앞에서 언급한 의사소통 방식에 따라 RequestBody의 writeTo(BufferedSink sink) 방법으로 파일 전송 진도를 감청합니다.
    //     
    RequestBody fileBody = LOkHttp3Utils.createProgressRequestBody(MediaType.parse("application/octet-stream"), file, 
      new ProgressListener() {
        @Override
        public void onStart() {
    
        }
    
        @Override
        public void onProgress(long total, float progress) {
            // progress       
        }
    
        @Override
        public void onFinish(File file) {
    
        }
    
        @Override
        public void onError(Exception e) {
    
        }
    });
    
    /**
     *     requestbody,        
     *
     * @param mediaType
     * @param file
     * @param listener
     * @return
     */
    public static RequestBody createProgressRequestBody(final MediaType mediaType, final File file,
           final ProgressListener listener) {
        return new RequestBody() {
            @Override
            public MediaType contentType() {
                return mediaType;
            }
    
            @Override
            public long contentLength() throws IOException {
                return file.length();
            }
    
            @Override
            public void writeTo(BufferedSink sink) throws IOException {
                listener.onStart();
                Source source;
                try {
                    source = Okio.source(file);
                    //sink.writeAll(source);
                    Buffer buf = new Buffer();
                    Long remaining = contentLength();
                    for (long readCount; (readCount = source.read(buf, 2048)) != -1; ) {
                        sink.write(buf, readCount);
                        listener.onProgress(contentLength(), 1 - (float)(remaining -= readCount) / contentLength());
                    }
                    listener.onFinish(file);
                } catch (Exception e) {
                    listener.onError(e);
                    e.printStackTrace();
                }
            }
        };
    }

    업로드 진행 모니터로 ProgressListener 인터페이스를 정의합니다.
    public interface ProgressListener {
    
        void onStart();
    
        void onProgress(long total, float progress);
    
        void onFinish(File file);
    
        void onError(Exception e);
    
    }

    GET 요청 파일 다운로드(진행률 막대 포함)
    여기는Callback 인터페이스를 다시 실현하여Response 대상의 파일 흐름을 가져와 파일 저장 작업을 하고 진행 상황을 감청하려면 파일 흐름을 읽을 때 처리해야 한다.
    1. 파일 다운로드(진행률 표시줄 없음)
    //       
    Request request = new Request.Builder()
            .url(url) //     
            .get()
            .addHeader("name", "value")
            .tag("getFileAsync")
            .build();
    
    final Call call = LOkHttp3Utils.okHttpClient().newCall(request);
    call.enqueue(new FileNoProgressCallback(Environment.getExternalStorageDirectory().getAbsolutePath(), "test.png") {
        @Override
        public void onFinish(File file) {
    
        }
    
        @Override
        public void onError(Exception e) {
    
        }
    });
    
    //   Callback  ,        
    public abstract class FileNoProgressCallback implements Callback {
    
        private String destFileDir;
    
        private String destFileName;
    
        public FileNoProgressCallback(String destFileDir, String destFileName) {
            this.destFileDir = destFileDir;
            this.destFileName = destFileName;
        }
    
        @Override
        public void onFailure(Call call, IOException e) {
            onError(e);
        }
    
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            this.saveFile(response);
        }
    
        private void saveFile(Response response) throws IOException {
            InputStream is = null;
            byte[] buf = new byte[2048];
            FileOutputStream fos = null;
    
            try {
                is = response.body().byteStream();
                final long total = response.body().contentLength();
                long sum = 0L;
                File dir = new File(this.destFileDir);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
    
                File file = new File(dir, this.destFileName);
                fos = new FileOutputStream(file);
    
                int len = 0;
                while ((len = is.read(buf)) != -1) {
                    sum += (long) len;
                    fos.write(buf, 0, len);
                }
    
                fos.flush();
                onFinish(file);
            } catch (Exception e) {
                onError(e);
            } finally {
                try {
                    response.body().close();
                    if (is != null) {
                        is.close();
                    }
                } catch (IOException var23) {
                }
    
                try {
                    if (fos != null) {
                        fos.close();
                    }
                } catch (IOException var22) {
                }
            }
        }
    
        public abstract void onFinish(File file);
    
        public abstract void onError(Exception e);
    
    }

    2. 파일 다운로드(!!!진행률 표시줄!!!)
    //     
    Request request = new Request.Builder()
            .url(url) //     
            .get()
            .addHeader("name", "value")
            .tag("getFileProgressAsync")
            .build();
    
    final Call call = LOkHttp3Utils.okHttpClient().newCall(request);
    call.enqueue(new FileCallback(Environment.getExternalStorageDirectory().getAbsolutePath(), "test.png") {
        @Override
        public void onStart() {
    
        }
    
        @Override
        public void onProgress(long total, float progress) {
    
        }
    
        @Override
        public void onFinish(File file) {
    
        }
    
        @Override
        public void onError(Exception e) {
    
        }
    });
    
    // FileCallback     Callback,            
    public abstract class FileCallback implements Callback, ProgressListener {
    
        private String destFileDir;
    
        private String destFileName;
    
        public FileCallback(String destFileDir, String destFileName) {
            this.destFileDir = destFileDir;
            this.destFileName = destFileName;
        }
    
        @Override
        public void onFailure(Call call, IOException e) {
            onError(e);
        }
    
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            this.saveFile(response);
        }
    
        private void saveFile(Response response) throws IOException {
            onStart();
            InputStream is = null;
            byte[] buf = new byte[2048];
            FileOutputStream fos = null;
    
            try {
                is = response.body().byteStream();
                final long total = response.body().contentLength();
                long sum = 0L;
                File dir = new File(this.destFileDir);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
    
                File file = new File(dir, this.destFileName);
                fos = new FileOutputStream(file);
    
                int len = 0;
                while ((len = is.read(buf)) != -1) {
                    sum += (long) len;
                    fos.write(buf, 0, len);
                    onProgress(total, (float) sum * 1.0F / (float) total);
                }
    
                fos.flush();
                onFinish(file);
            } catch (Exception e) {
                onError(e);
            } finally {
                try {
                    response.body().close();
                    if (is != null) {
                        is.close();
                    }
                } catch (IOException var23) {
                }
    
                try {
                    if (fos != null) {
                        fos.close();
                    }
                } catch (IOException var22) {
                }
            }
        }
    
    }

    좋은 웹페이지 즐겨찾기