[Product Name]

Retrofit

[Product Introduction]

Retrofit is currently a popular Android web request framework Retrofit home page, he is based on OkHttp for further encapsulation, the real network request work is OkHttp, but Retrofit uses dynamic proxy processing, etc. Let developers use a few annotations, very simple code to implement network requests. (ha ha 😄), about how Retrofit works, you can see my last article on the source code before no secrets – Retrofit source analysis, this article mainly discusses the use of Retrofit.

In order to facilitate the introduction of Retrofit, we built a simple API using Spring Boot

[Product Ingredients]

So much code source code

[Product Use]

Above all do not focus, the text begins, get on the car 🚲 walk

First, prepare work, introduce dependency

implementation 'com. Squareup. Retrofit2: retrofit: 2.8.1'
Copy the code

Write some code. Give me a Retrofit object

1. Define interfaces based on the API

interface ApiService {
    /** * GET request route friend_list * The request parameter is page * The corresponding data is in JSON format, and the method is defined according to the JSON data format. Return type * The return value is a Call package. Execute or enqueue can be called to initiate the network request */
    @GET("friend_list")
    fun getFriends(@Query("page") page:Int=1): Call<Result<List<User>>>
}
Copy the code

2. Create a Retrofit instance

        val retrofit = Retrofit.Builder()
                / / baseUrl API
                .baseUrl("HTTP: 192.168.31.7:8080 /")
                // add a Gson converter to convert the json data requested to the corresponding Java object
                .addConverterFactory(GsonConverterFactory.create())
                .build()
        // Use the create method to create an ApiService interface instance
        val apiService = retrofit.create(ApiService::class.java)
Copy the code

* * note: * * in (1) need to add a dependency implementation ‘com. Squareup. Retrofit2: converter – gson: 2.8.1’ general network request returns Json data, Using GsonConverterFactory, it helps to automatically convert the requested JSON data into the corresponding Java object

Make a network request

     apiService.getFriends().enqueue(object : Callback<Result<List<User>>> {
            override fun onFailure(call: Call<Result<List<User>>>, t: Throwable) {
                Log.i("MainActivity"."${t.message}")}override fun onResponse(call: Call<Result<List<User>>>, response: Response<Result<List<User> > >) {
                if (response.isSuccessful) {
                    Log.i("MainActivity"."success")
                    Log.i("MainActivity",response.body().toString())
                }else{
                    Log.i("MainActivity"."http code=${response.code()},message=${response.message()}")}}})Copy the code

Explanation: The getFriends() method returns a Call object, and calls enqueue to initiate an asynchronous request. The enqueue argument is the CallBack interface, which has two methods to Call back the network request failure, the exception onFailure, and the network request response onResponse. The onFailure and onResponse method callbacks are called from the main thread, so we don’t need to switch back to the main thread. Generally, when we say that the network request succeeds, it is HTTP code==200. OnResponse does not only go with code==200, it just means that the request is corresponding. Specifically, whether we want the success, we need to use response. This method considers HTTP code within [200,300] to be successful.

**Tip ** Retofit requires java8+ and android 21+ support, so you need to configure the android{} in the module build.gradle file as follows

android{
		...
    	compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

       kotlinOptions{
        jvmTarget="1.8"}}Copy the code

If there is no configuration above Compile this error message will appear when the Java. Util. Concurrent. ExecutionException: com. Android. View the r8. A: Invoke-customs are only supported starting with Android O (–min-api 26)

How do we define our interface methods according to the API

1. GET request submit form pass parameter (@query)

API: Request mode GET… /friend_list? The page=1&sort=desc parameter page, sort GET request method concatenates the parameter to the URL. Through? Connection parameter Synchronization between multiple parameters response result:

{
  "code": 0."msg": "success"."data": [{"id": 2."email": "[email protected]"."name": "Li"."sex": 1."age": 20."avatar": "https://212"},... ] }Copy the code

Retrofit method definition

   @GET("friend_list")
    fun getFriends(
        The value of the Query annotation is the name of the request parameter
        @Query("page") page: Int = 1.@Query("sort") sort: String
    ): Call<Result<List<User>>>
Copy the code

2. POST request to submit form (@field)

API: Request method POST… The email and password parameters are the response data in the request body

{
    "code": 0."msg": "success"."data": {
        "id": 3."email": "[email protected]"."name": "Emily"."sex": 1."age": 20."avatar": "https://111"}}Copy the code

Retrofit method definition

    @FormUrlEncoded
    @POST("login")
    fun login(
        @Field("email") email: String.@Field("password") password: String
    ): Call<Result<User? >>Copy the code

** Request parameters use @field annotation, method processing needs to add POST annotation, also need to add @Formurlencoded annotation, otherwise an error will be reported. Adding this annotation will add content-type =application/ ‘ ‘x-www-form-urlencoded data to the request Headers so that the request form parameters will encode the reference link in the URL encoding format


3. Dynamic URL, route parameter (@path)

API: Request mode GET… The /user/{id} parameter id is concatenated to the requested URL with /

{
  "code": 0."msg": "success"."data": {
    "id": 1."email": "[email protected]"."name": "xxxx"."sex": 1."age": 20."avatar": "https://xxxx"}}Copy the code

Retrofit method definition

    @GET("user/{id}")
    fun getUserInfo(@Path("id") id: Int): Call<Result<User? >>Copy the code

Note: The variable part of the URL is represented by {XXX}. When requesting, the @path parameter value will replace {XXX}. The value of @path must be the same as the value in {XXXX} braces defined in the route. For example, if you call getUserInfo(2), the request is… /user/2.

4. Submit json data (@body)

API: Request mode POST… /add_book request parameter is JSON data format as follows

{
  "name": "The first Line of Code."."author": "Guo Lin"."desc": "xxxxx"."cover": "xxxxx"
}
Copy the code

Response data:

{
  "code": 0."msg": "success"."data": {
    "name": "The first Line of Code."."author": "Guo Lin"."desc": "xxxxx"."cover": "xxxxx"}}Copy the code

Retrofit method definition

    @POST("add_book")
    fun addBook(@Body book: Book): Call<Result<Book>>
Copy the code

5.POST submits the form with the file and uploads the file

API: Request mode POST… /modify_user_info Request parameter name (string) and avatar (file) response result

{
    "code": 0."msg": "success"."data": null
}
Copy the code

The Retrofit method defines the first way

    @Multipart
    @POST("modify_user_info")
    fun modifyUserInfo(
        @Part("name") name: String.@Part file: MultipartBody.Part
    ): Call<Result<Nothing? >>Copy the code

** Explanation: ** Use @multipart to set content-type = ‘ ‘Multipart /form-data, and add @part annotation before the method parameter. Use @part annotation to declare value. For multipartBody. Part, no value can be entered. Let’s create multipartBody.part

		// The first step is to create a RequestBody object based on file or byte data
		val requestBody = RequestBody.create(MultipartBody.FORM, imageData)
        // Add the file. The first parameter is the parameters required by the API, the second parameter is the name of the file to be sent, and the third parameter is the RequestBody for the file data
        val part = MultipartBody.Part.createFormData("avatar"."android_logo.png", requestBody)
Copy the code

In the second way, you simply pass in the RequestBody object

  @POST("modify_user_info")
    fun modifyUserInfo(@Body body: RequestBody): Call<Result<Nothing? >>Copy the code

The RequestBody creation is as follows

		// Create a RequestBody object based on file or byte data
        val imageDataBody = RequestBody.create(MultipartBody.FORM, imageData)
        // Build a form body
        val multipartBody = MultipartBody.Builder()
                // Add normal key-value form data
            .addFormDataPart("name"."kk")
                // Add the file. The first parameter is the parameters required by the API, the second parameter is the name of the file to be sent, and the third parameter is the RequestBody for the file data
            .addFormDataPart("avatar"."android_logo.png", imageDataBody)
            .build()
Copy the code

Add more addFormDataPart if you have more than one file

6. Some other notes

1. @URL does not specify @get, @POST or other routes directly. Instead, @URL is used to modify the parameters of the method. eg.

    @GET
    fun getData(@Url url:String.@Query("page") page: Int = 1): Call<Result<List<User>>>
Copy the code

I think it’s generally useful for a class of apis where the argument and the return value are the same.

  1. @QueryMap

When there are many parameters but an uncertain number of parameters, you can use @xxxMap (@queryMap, @FieldMap, @PartMap) class annotations. eg.

    @GET("friend_list")
    fun getData(@QueryMap map: Map<String,String>): Call<Result<List<User>>>
Copy the code

@queryMap, @fieldMap, and @partMap are similar

Fifth, ConverterFactory

The converterFactory is responsible for converting the data returned by the network to the corresponding Java data type. Retrofit, by default, has a BuiltInConverters factory that converts the returned data into an OkHttp3.responseBody object. The above example we construct Retrofit objects through addConverterFactory (GsonConverterFactory. The create () method adds a GsonConverterFactory factory. If we don’t add this we’re going to have to change the return value of our upper interface

 @GET("friend_list")
    fun getData(@QueryMap map: Map<String,String>): Call<ResponseBody>
Copy the code

Retrofit officially gives us converter factories such as XML, Jackson, etc. Sometimes you want a Json string, don’t convert it to an object, so you can just write the return value as ResponseBody and handle the stream yourself, that’s one way to do it, but it’s too cumbersome, This time can use ScalarsConverterFactory conversion factory (you need to import the implementation ` ` ‘` ` com. Squareup. Retrofit2: converter – scalars ` ` : ` ` (insert the latest It converts the requested data into a String. And the return value of the method.

6. Kotlin coroutine support

Simply add Suspend before the method and return the result without a Call package, as shown below


    @GET("user/{id}")
    suspend fun getUserInfo1(@Path("id") id: Int):Result<User? >Copy the code

For more details, see my previous articles on the use of Kotlin coroutines in Android — Coroutines in Jetpack, coroutines in Retofit, and source analysis

[Manufacturing enterprises]

Square


Go to the hospital to take some medicine 💊 to drink recently, the instruction manual structure that sees medicine is quite clear still, write this article with respect to way of imitation medicine explanation (feel to be playful namely). Everyone knock code at the same time, also want to pay attention to the body, more exercise. Good health is the most important thing. Forget it. I’m taking my pills

Refer to the link

1. Form data 2.Retrofit home page


This article related source address