OkHttp + Retrofit example. From introducing dependencies, to writing interfaces, to making network requests.

Introduction of depend on

Introduce dependencies, using Retrofit2.

Implementation 'com. Squareup. Retrofit2: retrofit: 2.1.0' implementation 'com. Squareup. Retrofit2: converter - gson: 2.1.0' Implementation 'com. Squareup. Retrofit2: adapter - rxjava: 2.1.0'Copy the code
The query@Query

For example, the URL https://base_url/backend-service/config? Env =dev, the query content follows the question mark. For both GET and POST, use the @query annotation. Otherwise, an exception will be reported.

URL padding and concatenation

Pure URL padding can be annotated with @path. For example, the following POST request.

@POST("user-service/user/{uid}/token/refresh")
Call<RefreshTokenResp> refreshToken(@Path("uid") String uid, @Query("token") String token);
Copy the code
GET takes the parameters of the query
public interface CfgService { @GET("backend-service/config") Call<ServerCfgResp> getServerCfg(@Query("env") String env);  }Copy the code
POST, with parameters for the query and body
public interface UserService {

    @POST("user-service/login")
    Call<LoginResp> login(@Query("lenovoST") String token, @Query("realm") String realm,
                            @Body RequestBody body);

    @POST("user-service/logout")
    Call<CommonEntity> logout(@Query("token") String token, @Body RequestBody body);
}
Copy the code

RequestBody is created when called; Start by investigating the type of body the backend accepts.

Map<String, String> map = new HashMap<>();
        map.put("system", "Android");
        map.put("phoneBrand", Build.BRAND);
        map.put("modelNum", Build.MODEL);
        Gson gson = new Gson();
        String bodyJson = gson.toJson(map);
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), bodyJson);
Copy the code

Initialize OkHttpClient; All SSL certificates are trusted here (this is not recommended in formal environments).

private CfgService cfgService; public void initService() { SSLSocketFactory sslSocketFactory = null; try { sslSocketFactory = SSLUtils.getSSLSocketFactory(); } catch (Exception e) { e.printStackTrace(); } OkHttpClient.Builder builder = new OkHttpClient.Builder(); if (sslSocketFactory ! = null) { Log.d(TAG, "sslSocketFactory ! = null"); builder.sslSocketFactory(sslSocketFactory); } else { Log.w(TAG, "sslSocketFactory == null"); } builder.hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; // force return true}}); OkHttpClient lenClient = builder.build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(ServerCfg.HOST_URL) .client(lenClient) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build(); cfgService = retrofit.create(CfgService.class); }Copy the code
Call network request
mNetworkManager.getUserApi().login(mLenovoToken, ServerCfg.RID, requestBody).enqueue(new Callback<LoginResp>() { @Override public void onResponse(Call<LoginResp> call, final Response<LoginResp> response) { //... } @Override public void onFailure(Call<LoginResp> call, final Throwable t) { //... }});Copy the code
Trust SSL on all servers

This is not recommended

Public class SSLUtils {/** * @return trust all servers */ public static SSLSocketFactory getSSLSocketFactory() throws Exception {  SSLSocketFactory sslSocketFactory = null; SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, new TrustManager[]{createTrustAllManager()}, new SecureRandom()); sslSocketFactory = sslContext.getSocketFactory(); return sslSocketFactory; } public static X509TrustManager createTrustAllManager() { X509TrustManager tm = null; try { tm = new X509TrustManager() { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {//do nothing, } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {//do nothing, } public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0]; }}; } catch (Exception e) { } return tm; }}Copy the code
Service use IO. Reactivex. Observables
import io.reactivex.Observable; // @post ("feedbackAction") Observable<UserFeedback> userFeedback(@Query("appVersion") String appVersion, @Query("phoneModel") String phoneModel, @Query("phoneOsVersion") String osVersion, @Query("submitContent") String content);Copy the code

Examples – Retrofit2, RxJava2

Introduction of depend on
Implementation 'com. Squareup. Retrofit2: retrofit: 2.5.0' implementation 'com. Squareup. Retrofit2: converter - gson: 2.5.0' Implementation 'com. Squareup. Retrofit2: adapter - rxjava2:2.3.0' implementation 'IO. Reactivex. Rxjava2: rxandroid: 2.1.1' Implementation 'IO. Reactivex. Rxjava2: rxjava: 2.2.8'Copy the code
Define the interface
import java.util.Map; import io.reactivex.Observable; import retrofit2.http.Field; import retrofit2.http.FieldMap; import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; import retrofit2.http.POST; import retrofit2.http.Query; Public interface RustDroneCommonService {/** ** @param content ** * @param content */ @formurlencoded @post ("feedbackAction") Observable<FeedbackResp> userFeedback(@field ("appVersion") String appVersion, @Field("phoneModel") String phoneModel, @Field("phoneOsVersion") String osVersion, @Field("submitContent") String content, @FieldMap Map<String, String> map); /** * GET mobile phone verification code ** @param Mobile phone number */ @get ("verifyCode") Observable<PhoneCodeResp> getPhoneCode(@query ("mobile") String  mobile, @Query("oprType") int type); }Copy the code
Call interface
import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; RustDroneDataCenter.getCenter().getCommonService().userFeedback(BuildConfig.VERSION_NAME, Build.MODEL.replace(" ", "-"), Build.VERSION.RELEASE, fd, ext) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<FeedbackResp>() { @Override public void onSubscribe(Disposable d) { // LL.dn(TAG, "onSubscribe: " + d); } @Override public void onNext(FeedbackResp feedbackResp) { LL.dn(TAG, "onNext: " + feedbackResp); if (feedbackResp.getCode() == 0) { popSubmitSuccessDialog(); } else {ll. e(" failed to upload user feedback "); mPbLayout.setVisibility(View.GONE); popRetryDialog(); }} @override public void onError(Throwable e) {ll.e (" code: "+ e); mPbLayout.setVisibility(View.GONE); popRetryDialog(); } @Override public void onComplete() { mPbLayout.setVisibility(View.GONE); LL. Dn (TAG, "onComplete: upload complete "); }});Copy the code

OkHttp interview questions:

1. Briefly summarize OkHttp’s advantages

OkHttp is an excellent web request framework that Has been added to the Android source code by Google. The more popular Retrofit also uses OkHttp by default.

  • Easy to use, easy to expand.
  • Supports HTTP/2, allowing all requests to the same host to share the same socket connection.
  • If HTTP/2 is not available, use connection pool reuse to reduce request latency.
  • Support for GZIP, reducing download size.
  • Cache processing is supported to avoid repeated requests.
  • If your service has multiple IP addresses, OkHttp will try alternate addresses when the first connection fails.
  • OkHttp also handles proxy server issues and SSL handshake failures.

2. Describe the main workflow of OKHTTP

Step 1: Create Request and OkHttpClicent objects, wrap Request as a Call object, and Call the enQueue () method to perform the asynchronous Request;

Enqueue (AsyncCall) and promoteAndExecute(). Enqueue (AsyncCall) has two functions: Add AsyncCall to the readyAsyncCalls queue, and set the connection counter to the same Host. PromoteAndExecute () is responsible for actually scheduling AsyncCall resources: Iterate over readyAsyncCalls and place the request into runningAsyncCalls if the queue size that is executing does not exceed 64 and the connection counter of the same Host does not exceed 5. It then iterates through runningAsyncCalls, executing each request one by one;

AsyncCall submits itself to the thread pool for execution as a task, and then finishes.

3. OkHttp Interceptor class

Interceptors are a powerful mechanism provided in Okhttp that enables network listening, requests, and response rewriting, retries, and so on.

  • RetryAndFollowUpInterceptor: failed to retry and redirect the interceptor
  • BridgeInterceptor: a BridgeInterceptor, an interceptor that handles some of the required request headers
  • CacheInterceptor: a CacheInterceptor used to handle caches
  • ConnectInterceptor: a connection interceptor that establishes available connections. It is the basic of the CallServerInterceptor
  • CallServerInterceptor: The request server interceptor writes the HTTP request to the IO stream and reads the Response from the IO stream

4. Describe how to use OKHttp to initiate a network request.

The steps to initiate a web request using OKHttp are as follows:

  • New OKHttpClient
  • Create a Request object based on the requested URL

The parameters used during the Request are placed in the RequestBody of the Request object

  • Create a Call object using the Request object
  • Call.execute () for synchronous requests and call.enqueue for asynchronous requests
  • Gets and parses the request execution result object Response

5. How do I use OKHttp to process cookies?

There are two ways to use OKHttp for Cookie processing:

The first is manual processing, where response.headers() is used to retrieve all headers, including Cookie information, from the Response object for the callback. At this point, we can save the Cookie locally and add the Cookie information to the header the next time we make a network request.

The second is to use the Cookjar provided by OKHttp as follows:

builder = new OkHttpClient.Builder();  
builder.cookieJar(new CookieJar() {  
    private final HashMap<String, List<Cookie>> cookieStore = new HashMap<String, List<Cookie>>();  
  
    @Override  
    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {  
        cookieStore.put(url.host(), cookies);  
    }  
  
    @Override  
    public List<Cookie> loadForRequest(HttpUrl url) {  
        List<Cookie> cookies = cookieStore.get(url.host());  
        return cookies != null ? cookies : new ArrayList<Cookie>();  
    }  
});  
okHttpClient = builder.build();  
Copy the code

SaveFromResponse () is executed when the server response is received, and the Cookie information can be saved. LoadForRequest () is executed when the network request is initiated, and the saved Cookie information can be added.

6. What are the optimizations of OkHttp for network requests and how are they implemented?

OKHttp has the following major improvements over native HttpUrlConnection:

  • Support HTTP2 / SPDY
  • The socket automatically selects the best route and supports automatic reconnection
  • Automatic maintenance of the socket connection pool, reduce the number of handshakes, reduce the response delay
  • Have a queue thread pool, easy to write concurrency
  • Having Interceptors easily handle requests and responses (e.g. Transparent GZIP compression,LOGGING)
  • Headers based caching strategy to avoid repeated network requests

Android development: framework source code parsing video reference