preface

Abstract

Network request is to realize the data transfer between the client (APP) and the server (where the data is stored), which is basically a necessary function of every APP. All network related logic runs through the whole APP. The stability, ease of use and packaging quality of network related framework directly affect the quality of projects. As technology matures, network requests can be quickly implemented using popular third-party frameworks.

This article is mainly for the advanced knowledge, through OkHttp+Retrofit+RxAndroid to achieve a network request, and at the same time gives the method of entry learning.

Tripartite framework introduction + learning method

Our whole network is divided into the underlying network request (request details of the real network), network top request (easy to trigger the underlying request method), result analysis, and reactive programming business processes involves network (simplified), method of study, of course, is the first master the basic knowledge, understand the basic use, cooperate to use again in order to achieve will converge

1. OkHttp (Network Underlying Framework)

An open source project for handling low-level web requests, android’s most popular lightweight framework, contributed by Square (which also contributed Picasso) to replace HttpUrlConnection and Apache HttpClient(Android API23) HttpClient has been removed from 6.0.

Based learning address: www.jianshu.com/p/da4a806e5…

2. Retrofit

A framework for converting HTTP apis into Java interface form. While Okhttp has done a lot of low-level wrapping to make it easy to call, Retrofit exists to further simplify the process of writing a lot of tedious and repetitive request logic for each request

Based learning address: cloud.tencent.com/developer/a…

3. RxAndorid (Responsive Programming Framework)

Functional responsive programming = functional programming + responsive programming. Designed to greatly simplify projects, especially when dealing with asynchronous events for nested callbacks, complex list filtering and transformations, and time-dependent issues, RxAndorid implements responsive programming that is unique to Android, similar to and distinct from Rxjava.

4. Json Parsing framework (result parsing)

If steps 1, 2, and 3 are processes, then step 4 is the processing of results. Here we use Google Gon for result parsing (that is, converting XML data from the network into the desired data format for processing and passing during encoding).

The implementation process

Basically know what they are, to focus on how they say to use together

1. Configure the network request address

Since we’re going to implement a network request, there must be a request address, right? (Request simply means to get the corresponding data from the corresponding server)

Configuration method

Android Studio offers productFlavors, which makes it easy to configure and switch environments, such as development, testing, formal, pre-launch, etc., and implement channel packages.

A channel package is a corresponding APK with the respective app market identity, which is used to facilitate specific statistics such as downloads for each app market

The process is as follows:

1) Add the following code to your App /build.gradle android method:

// Configure different environments
productFlavors{
    // Development environment, ENDPOINT data address, here I am using a Courier API
    dev {
        / / API endpoint
        ```
        buildConfigField('String'."ENDPOINT".'" http://www.kuaidi100.com/query?type= express company code & postid = express number "')

        dimension = minSdkVersion
    }

    // Formal environment
    prod {
        / / API endpoint
        buildConfigField 'String'.'ENDPOINT'.'" http://www.kuaidi100.com/query?type= express company code & postid = express number "'

        dimension = minSdkVersion
    }
}
Copy the code

2) rebuild

After rebuild, you can switch the address in Build Varians. Now we have selected the development environment :dev

3) Configure network address constants

/** * constant class */
public class Constant {
    public static final String ENDPOINT = BuildConfig.ENDPOINT;
}
Copy the code

# # # # note: The advantage of this configuration is that every time we change the environment from Build Varians, the ENDPOINT field in the Constant class automatically changes to the environment address, so that we do not have to change the environment address each time (the same goes for other environment-related information). You can study productFlavors carefully, which can improve the development efficiency

2. Add dependencies

    //okhttp
    implementation 'com. Squareup. Okhttp3: okhttp: 4.2.0'

    //retrofit
    implementation 'com. Squareup. Retrofit2: retrofit: 2.6.2'

    // Use gson to parse json
    implementation 'com. Google. Code. Gson: gson: 2.8.5'

    // Retrofit uses gson parsing
    // Version should be the same as Retrofit
    implementation 'com. Squareup. Retrofit2: converter - gson: 2.6.2'

    Retrofit supports RXJava
    implementation 'com. Squareup. Retrofit2: adapter - rxjava2:2.6.2'
Copy the code

3. Code implementation

Step 1: Create the entity class that receives the data

When we request data from the network, we have to have a place to receive the data, and the place to receive the data is what we call the data entity class

The format of the data entity depends on the format of the data returned by the network. The following figure shows the format of the data after the request is initiated :(directly taking the error message as an example)

As you can see from the above figure, the return is a standard Json format, so we can create an entity class that corresponds to the corresponding field one by one:

public class Delivery {
    private String message;

    private String nu;

    private String ischeck;

    private String condition;

    private String com;

    private String status;

    private String state;

    public String getMessage(a) {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getNu(a) {
        return nu;
    }

    public void setNu(String nu) {
        this.nu = nu;
    }

    public String getIscheck(a) {
        return ischeck;
    }

    public void setIscheck(String ischeck) {
        this.ischeck = ischeck;
    }

    public String getCondition(a) {
        return condition;
    }

    public void setCondition(String condition) {
        this.condition = condition;
    }

    public String getCom(a) {
        return com;
    }

    public void setCom(String com) {
        this.com = com;
    }

    public String getStatus(a) {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getState(a) {
        return state;
    }

    public void setState(String state) {
        this.state = state; }}Copy the code

Step 2: Create the network request interface

We know that in the past, network requests required a lot of configuration code to initiate the request, isn’t it very troublesome? This was liberated by Retrofit, which took the code for complex requests and turned it into an interface that encapsulated complex logic and exposed only a minimalist interface

public interface Request {
    // Retrofit: Network requests in the form of interfaces
    // Delivery is used to receive the result, which is the entity class we just created
    @GET("")
    Observable<Delivery> delivery(a);
}
Copy the code

Step 3: Initialize the request configuration

        // The implementation of the underlying request is handed over to OkHTTP (although Retrofit uses okHTTP for the underlying request, it is configured separately here so that we can customize the interceptor. Interceptors are not discussed here.)
        OkHttpClient.Builder builder = new OkHttpClient.Builder();

        Create a Retrofit
        Retrofit retrofit = new Retrofit.Builder()
                .client(builder.build())
                // Set the base address
                .baseUrl(Constant.ENDPOINT)
                // ADAPTS rXJava for the purpose of using the observer pattern to decompose the process of the upper layer request, so that we can easily intervene (such as request nesting)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                // Use the Gson framework to parse the result returned by the request, because it is XML, and only after parsing, can the data be turned into objects, and placed in the entity class we just created you, for easy data transfer
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        // Create a request
       Request request = retrofit.create(Request.class);
Copy the code

Step 4: Initiate the request

        request.delivery()
                // Initiate the request in the child thread
                .subscribeOn(Schedulers.io())
                // The results are processed in the main thread, as UX updates are often required
                .observeOn(AndroidSchedulers.mainThread())
                // Observer mode turns on subscription to receive the result of the send request event
                .subscribe(new Observer<Delivery>() {
                    @Override
                    public void onSubscribe(Disposable d) {}@Override
                    public void onNext(Delivery delivery) {
                        // Request a successful callback and get the result data delivery
                    }

                    @Override
                    public void onError(Throwable e) {
                        // The request fails to be called back. Exception E is reported
                    }

                    @Override
                    public void onComplete(a) {
                        // Request an end callback}});Copy the code

Advanced usage

Usage 1: Nested requests

Step 1: Define the interfaces for the first and second requests

        Observable<Delevery1> observable1;
        Observable<Delevery2> observable2;
Copy the code

Step 2: Use Observable<… > encapsulates two network requests

        observable1 = request.delivery1();
        observable2 = request.delivery2();
Copy the code

Step 3: Use the transform operator FlatMap for nested requests

FlatMap: Split the sequence of events sent by the observer & transform it separately, then merge it into a new sequence of events, and finally send itCopy the code
// Switch to the IO thread for network request 1
 observable1.subscribeOn(Schedulers.io())
         // (new observer) switches to the main thread to process the result of network request 1
         .observeOn(AndroidSchedulers.mainThread())
         .doOnNext(new Consumer<Delivery1>(){
@Override
public void accept(Delivery1 result)throws Exception{
        Log.d(TAG,"The first network request succeeded");
        result.show();
        // Operate on the result returned by the first network request
        }
        })
        .observeOn(Schedulers.io())
        // Since flatMap is applied to the original observer, it is the new observer for the old observer, so observeOn is required to switch threads
        // But for the original observer, it is the new observed
        // Change the original event (request 1) to a new event (request 2) in a new thread
        .flatMap(new Function<Delivery1, ObservableSource<Delivery2>>(){
@Override
public ObservableSource<Delivery2> apply(Delivery1 result)throws Exception{
        // Convert network request 1 to network request 2, i.e. send network request 2
        returnobservable2; }})// (initial observer) switches to the main thread to process the result of network request 2
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Consumer<Delivery2>(){
@Override
public void accept(Delivery2 result)throws Exception{
        Log.d(TAG,"Second network request successful");
        result.show();
        // Operate on the result returned by the second network request}},new Consumer<Throwable>(){
@Override
public void accept(Throwable throwable)throws Exception{}}); }Copy the code

Technology stack analysis

Question: What are the advantages and disadvantages of using okHTTP, Retrofit, RxJava, and Gson together?Copy the code

Advantages:

1: Help to quickly implement network role requests, ignoring the low-level implementation details, allowing developers to focus more on the business layer
2: Web requests in the form of interfaces are more in line with Java programming specifications, while Retrofit softeners the best of each framework to help developers solve more complex problems in a more elegant way

Disadvantages:

1: It is difficult to get started and requires high skills of developers