[see the true chapter for Demo] transplant Android Retrofit to Hongmeng system, and implement a set of network request framework on Hongmeng system

1, Highlights:

Since the release of Hongmeng mobile version, I have been doing the work of porting Android code to Hongmeng system. Retrofit is an excellent network request framework on Android system. Hongmeng system has no similar network request framework. So I decided to implement a set of Hongmeng version of retrofit.

Jianjia is a network request framework on Hongmeng system. In fact, it is to transplant Android retrofit to Hongmeng system. I named the retrofit of Hongmeng version Jianjia. Jianjia can not only realize the function of retrofit, but also provide some functions that retrofit does not have. Retrofit does not support dynamic domain name replacement. Domestic applications generally have multiple domain names. Jianjia supports dynamic domain name replacement. Retrofit cannot add interceptors directly. It can only add interceptors through okhttp. Jianjia will support adding interceptors.

2, Demo compilation and effect presentation are as follows:

Demo demo video stamp this

Note: the document attachment is at the bottom

3, Source code:

https://gitee.com/zhongte/JianJia

To understand the source code, you need to have the following skills.

Familiar with common usage of okhttp

Familiar with interface oriented programming, reflection, generics and annotation

Familiar with constructor mode, adapter mode, factory mode, policy mode, static agent, dynamic agent, responsibility chain mode and other design modes

4, The usage is the same as Retrofit

Jianjia provides a series of annotations, which are needed when making network requests.

4.1 GET annotation

Create an interface and use the GET annotation in the method. The GET annotation is used to identify that this is a GET request. The return value of the method is the call object and the generic type is the ResponseBody. In fact, the generic type can also be a specific entity object, which will be discussed later. How does jianjia complete the network request? Use constructor mode to create jianjia object. baseUrl is the domain name. When creating jianjia object, you must specify the domain name. Call the Create method to generate an instance of the interface, and call Wan getBanner(). Enqueue to execute the network request. If the request succeeds, the onResponse method will be called back, and if the request fails, the onFailure method will be called back

public interface Wan {

    @GET("banner/json")
    Call<ResponseBody> getBanner();
}

JianJia jianJia = new JianJia.Builder()
        .baseUrl("https://www.wanandroid.com")
        .build();

Wan wan = jianJia.create(Wan.class);
wan.getBanner().enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
        try {
            String json = response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        LogUtils.info("yunfei", t.getMessage());
    }
});

4.2 BaseUrl annotation

Domestic applications generally have multiple domain names. BaseUrl annotation can set a separate domain name for an interface.

public interface Wan {

    @BaseUrl("https://api.apiopen.top")
    @GET("getJoke")
    Call<ResponseBody> getJoke(@QueryMap Map<String, String> param);
    
}

4.3 notes

The Path annotation replaces the specified parameter value in the Path and defines the following method. We can see that we have defined a getArticle method, which receives a page parameter, and our @ GET annotation uses {page} to declare the access Path. Here you can use {page} as a placeholder, and in actual operation, it will be replaced by the parameters marked by @ Path("page").

public interface Wan {

    @GET("article/list/{page}/json")
    Call<ResponseBody> getArticle(@Path("page") int page);

}

4.4 Query annotation

Query annotation is used to add request parameters to get requests. The parameter types modified by query annotation can be array, set, string, etc

public interface Wan {

    @GET("wxarticle/list/405/1/json")
    Call<ResponseBody> search(@Query("k") String k);

    @GET("wxarticle/list/405/1/json")
    Call<ResponseBody> search(@Query("k") String... k);

    @GET("wxarticle/list/405/1/json")
    Call<ResponseBody> search(@Query("k") List<String> k);

}

4.5 QueryMap annotation

QueryMap annotation adds query parameters in the form of map. The parameter type modified by QueryMap annotation must be map object

public interface Wan {

    @GET("wxarticle/list/405/1/json")
    Call<ResponseBody> search(@QueryMap Map<String, String> param);
    
}

4.6 SkipCallbackExecutor annotation

In Hongmeng system, the response of the server will be called back to the main thread by default. If the skippcallbackexecutor annotation is used on the method, the result of the server will not be called back to the main thread

public interface Wan {
    @SkipCallbackExecutor
    @GET("wxarticle/list/405/1/json")
    Call<ResponseBody> search(@QueryMap Map<String, String> param);
    
}

4.7 FormUrlEncoded annotation and Field annotation

The FormUrlEncoded annotation is used to send a form request. Using this annotation, Field annotation must be added to the parameters of the method. The parameter types modified by Field annotation can be array, set, string, etc

public interface Wan {
    @POST("user/login")
    @FormUrlEncoded
    Call<ResponseBody> login(@Field("username") String username, @Field("password") String password);
    
}

4.8 FormUrlEncoded annotation and FieldMap annotation

Sometimes the form has more parameters. If Field annotation is used, the method will have more parameters. At this time, fieldMap annotation can be used. FieldMap annotation sends a form request in the form of map. If the parameter modified by the fieldMap annotation is not of map type, an exception will be thrown. If the key value pair of the map is empty, an exception will also be thrown.

public interface Wan {
    @POST("user/login")
    @FormUrlEncoded
    Call<ResponseBody> login(@FieldMap Map<String, String> map);
    
}

4.9 Body notes

The server will ask the client to send the json string as the request Body to the server. At this time, the parameters defined by the Body annotation can be directly passed into an entity class. The entity will be serialized internally and the serialized results will be sent directly as the request Body.

If the type of the parameter modified by the Body annotation is the RequestBody object, the caller can not add a data converter, and the default data converter will be used internally

If the type of the parameter modified by the Body annotation is not a RequestBody object but a specific entity class, the caller needs to customize a class and inherit converter Factory

public interface Wan {

    /**
     * The type of the parameter modified by the Body annotation is the RequestBody object. The caller can not add a data converter, and the default data converter will be used internally
     *
     * @param body
     * @return
     */
    @POST("user/register")
    Call<ResponseBody> register(@Body RequestBody body);

    /**
     * The type of the parameter modified by the Body annotation is not a RequestBody object, but a specific entity class. The caller needs to customize a class and inherit converter Factory
     * 
     * @param user
     * @return
     */
    @POST("user/register")
    Call<ResponseBody> register(@Body User user);
}

4.10 Url annotation

The Url annotation is used to add the full address of the interface. In retrofit, if the domain name of the interface is different from the domain name specified by creating the retrofit object, the Url annotation will be used to solve the problem. In Jianjia, the Url annotation can also be used to solve the problem, but Jianjia also provides BaseUrl to solve the problem.

public interface Wan {

    @GET()
    Call<ResponseBody> getArticle(@Url String url);
    
}

4.11 Headers annotation

Headers annotations are annotations that act on methods and are used to add one or more request headers.

public interface Wan {

    @Headers("Cache-Control: max-age=640000")
    @GET("/")
    Call<ResponseBody> getArticle(@Url String url);
    
    @Headers({
     "X-Foo: Bar",
     "X-Ping: Pong"
   })
    @GET("/")
    Call<ResponseBody> getArticle(@Url String url);
    
}

4.12 Header annotation

Header annotation is an annotation that acts on parameters and is used to add request headers

public interface Wan {

    @GET()
   Call<ResponseBody> foo(@Header("Accept-Language") String lang);
    
}

4.13 HeaderMap annotation

The HeaderMap annotation is an annotation that acts on parameters. The request header is added in the form of map. The key and value of each item in the map cannot be empty, otherwise an exception will be thrown

public interface Wan {

    @GET("/search")
   Call<ResponseBody> list(@HeaderMap Map<String, String> headers);
    
}

5, Add data converter

Previously, when we defined a method in the interface, the return value of the method is the Call object, and the generic type is ResponseBody. In this case, the data returned by the service end to the end will be in the ResponseBody. The end needs to manually parse json and parse json into an entity class.

In fact, we don't need to parse json manually. We can let gson parse json for us. Jianjia supports adding data converters when creating objects, that is, adding gson. In the onResponse method, we can directly get the entity class object. Gson helps us resolve json into an entity class.

public interface Wan {

    @GET("banner/json")
    Call<Banner> getBanner();
}

JianJia jianJia = new JianJia.Builder()
        .baseUrl("https://www.wanandroid.com")
        .addConverterFactory(GsonConverterFactory.create())
        .build();

Wan wan = jianJia.create(Wan.class);
wan.getBanner().enqueue(new Callback<Banner>() {
    @Override
    public void onResponse(Call<Banner> call, Response<Banner> response) {
        try {
            if (response.isSuccessful()) {
                Banner banner = response.body();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFailure(Call<Banner> call, Throwable t) {
        LogUtils.info("yunfei", t.getMessage());
    }
});

6, Follow up work of Jianjia

6. 1. Annotations are also required for uploading files. At present, Jianjia has no annotations for uploading files, and the annotations for uploading files are under development.
6. 2. Jianjia does not support adding interceptors directly at present, and the functions of interceptors will be added later.
6. 3 secondary encapsulation of network request framework. The secondary encapsulation of network request framework should isolate the third-party network framework. If there is a better network framework in the future, or the company requires to use the network framework developed by the company, the previous network framework can be easily replaced without major changes.
6. Due to the epidemic situation, I estimate that I have to spend the new year in Beijing and can't go back to my hometown for the new year. So you can record videos for everyone during the holiday. Hand in hand to ask you to implement their own network framework, hoping to help you understand the implementation principle of Jianjia. Principle of principle is as like as two peas of Retrofit. Jianjia itself is transplanted from retrofit, but Jianjia can run on Hongmeng system.

Original link: https://developer.huawei.com/consumer/cn/forum/topic/0204470884054220049?fid=0101303901040230869

Original author: Yibo Yuntian Xiaoguan Yu

Posted by fitchn on Mon, 18 Apr 2022 02:28:57 +0930