OKHttp quick start

Posted by Lodius2000 on Mon, 22 Jun 2020 09:31:27 +0200

OKHttp quick start

OKHttp quick start

Official website: https://square.github.io/okhttp/

Code warehouse: https://github.com/square/okhttp

The library is a third-party library, which is used to request network and supports synchronous and asynchronous request modes

Synchronization request

get

For the synchronization request, the sub thread needs to be opened at the time of request. After the request is successful, the user needs to jump to the UI thread to modify the UI.

public void getDatasync(){
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                OkHttpClient client = new OkHttpClient();//Create OkHttpClient object
                Request request = new Request.Builder()
                        .url("http://www.baidu.com")//Request interface. If you need to splice parameters to the back of the interface.
                        .build();//Create Request object
                Response response = null;
                response = client.newCall(request).execute();//Get Response object
                if (response.isSuccessful()) {
                Log.d("kwwl","response.code()=="+response.code());
                Log.d("kwwl","response.message()=="+response.message());
                Log.d("kwwl","res=="+response.body().string());
                //At this time, the code is executed in the sub thread. Please use handler to jump to UI thread for UI modification.
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }).start();
}

The print results are as follows:
response.code()==200;
response.message()OK;
res{"code":200,"message":success};

matters needing attention:

  1. Response.code It is the code in the http response line. If the access is successful, it will return 200. This is not set by the server, but it comes with the http protocol. The code in res is set by the server. Pay attention to the difference between them.
  2. response.body().string() is essentially a read operation of the input stream, so it is also part of the network request, so this line of code must be placed in the child thread.
  3. response.body().string() can only be called once, with a return value on the first call and null on the second call. as a result of: response.body().string() is essentially a read operation of the input stream. Only when there is a write operation of the output stream of the server can the client read the data. However, the write operation of the server is only performed once, so the read operation of the client can only be performed once, and null will be returned the second time.

Asynchronous request

get

In this way, you don't need to open the sub thread again, but the callback method is executed in the sub thread, so you need to jump to the UI thread when updating the UI.
Examples of use are as follows:

private void getDataAsync() {
    OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder()
            .url("http://www.baidu.com")
            .build();
    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
        }
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if(response.isSuccessful()){//The method of the callback is executed in the child thread.
                Log.d("kwwl","Data acquisition succeeded");
                Log.d("kwwl","response.code()=="+response.code());
                Log.d("kwwl","response.body().string()=="+response.body().string());
            }
        }
    });
}

The printing results and precautions of asynchronous request are the same as those of synchronous request. The biggest difference is that the asynchronous request does not need to start the sub thread, and enqueue method will automatically put the network request part into the sub thread for execution.

matters needing attention:

  1. The onFailure method and onResponse of the callback interface are executed in the child thread.
  2. response.body().string() method must also be placed in a child thread. When the result of executing this line of code is obtained, jump to UI thread to modify UI.

post

private void postDataWithParame() {
    OkHttpClient client = new OkHttpClient();//Create the OkHttpClient object.
    FormBody.Builder formBody = new FormBody.Builder();//Create form request body
    formBody.add("username","zhangsan");//Pass key value pair parameter
    Request request = new Request.Builder()//Create a Request object.
            .url("http://www.baidu.com")
            .post(formBody.build())//Delivery request body
            .build();
    client.newCall(request).enqueue(new Callback() {. . . });//The use of callback method is the same as that of get asynchronous request, omitted at this time.
}

be careful: request.post It accepts a requestbody object. As long as it is a subclass of the object, it can be passed as a parameter, and formbody is a subclass of the object

Reference summary:

  1. character string key value yes:

    Refer to the form body above

  2. json String:

    OkHttpClient client = new OkHttpClient();//Create the OkHttpClient object.
    MediaType mediaType = MediaType.parse("application/json; charset=utf-8");//The data type is json format,
    String jsonStr = "{\"username\":\"lisi\",\"nickname\":\"Li Si\"}";//json data
    RequestBody body = RequestBody.create(mediaType, josnStr);
    Request request = new Request.Builder()
            .url("http://www.baidu.com")
            .post(body)
            .build();
    client.newCall(request).enqueue(new Callback() {. . . });//The callback method is omitted here.
    
  • File object:

    OkHttpClient client = new OkHttpClient();//Create the OkHttpClient object.
    MediaType fileType = MediaType.parse("File/*");//The data type is json format,
    File file = new File("path");//file object.
    RequestBody body = RequestBody.create(fileType , file );
    Request request = new Request.Builder()
            .url("http://www.baidu.com")
            .post(body)
            .build();
    client.newCall(request).enqueue(new Callback() {. . . });//The callback method is omitted here.
    
  • Blend objects:

    OkHttpClient client = new OkHttpClient();
    MultipartBody multipartBody =new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("groupId",""+groupId)//Add key value pair parameter
            .addFormDataPart("title","title")
         .addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("file/*"), file))//Add file
            .build();
    final Request request = new Request.Builder()
            .url(URLContant.CHAT_ROOM_SUBJECT_IMAGE)
            .post(multipartBody)
            .build();
    client.newCall(request).enqueue(new Callback() {. . . });
    

    Note: there is no difference between addFormDataPart and addPart, but there is an additional layer of encapsulation

    /** Add a form data part to the body. */
    public Builder addFormDataPart(String name, String value) {
        return addPart(Part.createFormData(name, value));
    }
    
    /** Add a form data part to the body. */
    public Builder addFormDataPart(String name, String filename, RequestBody body) {
        return addPart(Part.createFormData(name, filename, body));
    }
    
    public static Part createFormData(String name, String value) {
        return createFormData(name, null, RequestBody.create(null, value));
    }
    
    public static Part createFormData(String name, String filename, RequestBody body) {
        if (name == null) {
            throw new NullPointerException("name == null");
        }
        StringBuilder disposition = new StringBuilder("form-data; name=");
        appendQuotedString(disposition, name);
    
        if (filename != null) {
            disposition.append("; filename=");
            appendQuotedString(disposition, filename);
        }
    
        return create(Headers.of("Content-Disposition", disposition.toString()), body);
    }
    
  • Flow object:

    RequestBody body = new RequestBody() {
        @Override
        public MediaType contentType() {
            return null;
        }
    
        @Override
        public void writeTo(BufferedSink sink) throws IOException {//Override writeTo method
            FileInputStream fio= new FileInputStream(new File("fileName"));
            byte[] buffer = new byte[1024*8];
            if(fio.read(buffer) != -1){
                 sink.write(buffer);
            }
        }
    };
    
    OkHttpClient client = new OkHttpClient();//Create the OkHttpClient object.
    Request request = new Request.Builder()
            .url("http://www.baidu.com")
            .post(body)
            .build();
    client.newCall(request).enqueue(new Callback() {. . . });
    
    

    The difference of the above code is the body object, which rewrites the write method and contains a sink object. This is the output stream in OKio package, with write method. With this method, we can realize the function of upstream flow.

  • When using RequestBody to upload a file, it does not implement the function of resuming a breakpoint. I can use this method in combination with RandomAccessFile class to realize the function of breakpoint continuation

    Set request header

    Request request = new Request.Builder()
                    .url("http://www.baidu.com")
                    .header("User-Agent", "OkHttp Headers.java")
                    .addHeader("token", "myToken")
                    .build();
    

    Download File

    The function of downloading files is not provided in OKHttp, but the stream object can be obtained in Response. With the stream object, we can download files ourselves. The code is as follows:
    This code is written in the onResponse method of CallBack interface CallBack:

    try{
        InputStream  is = response.body().byteStream();//Get input stream object from server
        long sum = 0;
        File dir = new File(mDestFileDir);
        if (!dir.exists()){
            dir.mkdirs();
        }
        File file = new File(dir, mdestFileName);//Get file object according to directory and file name
        FileOutputStream  fos = new FileOutputStream(file);
        byte[] buf = new byte[1024*8];
        int len = 0;
        while ((len = is.read(buf)) != -1){
            fos.write(buf, 0, len);
        }
        fos.flush();
        return file;
    
    }
    

    Another example of file download:

    OkHttpClient client = new OkHttpClient();
    Request request = new Request.Builder()
        .url(url)
        .build();
    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            e.printStackTrace();
        }
    
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if (response.isSuccessful()){
                downlodefile(response, Environment.getExternalStorageDirectory().getAbsolutePath(),"text.txt");
            }
        }
    });
    
    private void downlodefile(Response response, String url, String fileName) {
        InputStream is = null;
        byte[] buf = new byte[2048];
        int len = 0;
        FileOutputStream fos = null;
        try {
            is = response.body().byteStream();
            //file size
            long total = response.body().contentLength();
            File file = new File(url, fileName);
            fos = new FileOutputStream(file);
            long sum = 0;
            while ((len = is.read(buf)) != -1) {
                fos.write(buf, 0, len);
                //                progress bar
                //                sum += len;
                //                int progress = (int) (sum * 1.0f / total * 100);
            }
            fos.flush();
            Log.e("xxxxxxxx", "Download successful");
        } catch (Exception e) {
        } finally {
            try {
                if (is != null)
                    is.close();
            } catch (IOException e) {
            }
            try {
                if (fos != null)
                    fos.close();
            } catch (IOException e) {
            }
        }
    }
    

    encapsulation

    OKHttpUtils of hongyang God is the first to encapsulate OKHttpUtils

    Interceptor

    Interceptors It's an interceptor in Okhttp. It's officially introduced that interceptor is a powerful listener, which can be rewritten. For more details, please see Interceptors of okhttp wiki , this article can be regarded as Chinese version.

      Response getResponseWithInterceptorChain() throws IOException {
        // Build a full stack of interceptors.
        List<Interceptor> interceptors = new ArrayList<>();
        interceptors.addAll(client.interceptors());
        interceptors.add(retryAndFollowUpInterceptor);
        interceptors.add(new BridgeInterceptor(client.cookieJar()));
        interceptors.add(new CacheInterceptor(client.internalCache()));
        interceptors.add(new ConnectInterceptor(client));
        if (!forWebSocket) {
          interceptors.addAll(client.networkInterceptors());
        }
        interceptors.add(new CallServerInterceptor(forWebSocket));
    
        Interceptor.Chain chain = new RealInterceptorChain(
            interceptors, null, null, null, 0, originalRequest);
        return chain.proceed(originalRequest);
      }
    

    From this, we can find that okhttp uses interceptor mechanism when processing network response. Okhttp uses ArrayList to manage the interceptors, which will be called in turn.

    As shown in the figure above:

    1. In the orange box are the implementation classes of Interceptors provided by okhttp. They are all in the call.getResponseWith InterceptorChain () added In the Interceptor chain, in fact, these Interceptors were introduced after okhttp3. They are very important. They are responsible for the whole process of reconnection, assembly of request headers, read / write cache, establishment of socket connection, and sending request / receive response to the server.

    2. Before okhttp3, these behaviors were encapsulated in the HttpEngine class. After okhttp3, HttpEngine has been deleted and replaced by these five interceptors. It can be said that the details in a network Request are decoupled in different interceptors. Different interceptors are only responsible for their own part of the work (get / process the Request or Response), making the Interceptor mode completely throughout the whole network Request.

    3. Users can add custom interceptors. okhttp divides interceptors into application interceptors and network interceptors

     public class OkHttpClient implements Cloneable, Call.Factory {
      final List<Interceptor> interceptors;
      final List<Interceptor> networkInterceptors;
      ......
      }
    
    • call OkHttpClient.Builder addInterceptor() of can add application interceptors, which will only be called once, and can handle the final Response back from the network request
    • Call addNetworkInterceptor() to add a network interceptor and process all network responses (if a request is redirect ed, the logic of the interceptor may be called twice)
    1. Application interceptors and Network Interceptors
    Application interceptor

    There is no need to worry about intermediate process responses, such as redirection and retry
    Always call once, even if the HTTP response is taken from the cache
    Observe the original intention of the application. Do not care about the header information of OkHttp injection, such as if none match
    Allow short circuit without calling Chain.proceed(), which aborts the call
    Allow retries, make Chain.proceed() called more than once

    Network connector

    Ability to manipulate intermediate process responses, such as redirection and retry
    It is not called when the network is short circuited and the cache response is returned
    Only data transmitted over the network is observed
    Carry the request to access the connection

    CopyFrom:

    https://blog.csdn.net/fightingxia/article/details/70947701

    https://www.jianshu.com/p/f5320b1e0287

    Reference:

    Analysis of OkHttp source code -- the logical flow of HTTP request
    Interceptors of okhttp wiki

    Topics: OkHttp network JSON github