The retrofit usage of Android development

Source: Internet
Author: User
Tags http request http request header parameters throwable

Retrofit is a framework developed by the Square company for the Android network, RETROFIT2 based on Okhttp, Okhttp is now officially recognized by Google, and a large number of apps are using okhttp to make network requests, Its source details see Okhttp Github.

This article is all in the retrofit2.0+ version based on the discussion, using all the examples from the Watercress API

First let's look at how a complete GET request is implemented:

Create a business request interface with the following specific code:

The code is as follows Copy Code
Public interface Blueservice {
@GET ("Book/search")
Call<booksearchresponse> Getsearchbooks (@Query ("q") String name,
@Query ("tag") String tag, @Query ("start") int start,
@Query ("Count") int count);
}

Here is a little explanation, @GET annotations represent get requests, @Query represent request parameters that will be key=value in the back of the URL

You need to create a retrofit example and complete the appropriate configuration

The code is as follows Copy Code

Retrofit RETROFIT = new Retrofit.builder ()
. BaseURL ("https://api.douban.com/v2/")
. Addconverterfactory (Gsonconverterfactory.create ())
. build ();

Blueservice service = retrofit.create (Blueservice.class);

The BaseURL here is the network request URL relatively fixed address, generally including the request protocol (such as HTTP), domain name or IP address, port number, of course, there will be many other configurations, described in detail below. There is also a Addconverterfactory method that indicates what converters need to be used to resolve the return value, and Gsonconverterfactory.create () indicates that the Gson library is invoked to parse the JSON return value, as described in detail below.

Invoke the request method and get the call instance

Call<booksearchresponse> call = Mblueservice.getsearchbooks ("The Little Prince", "", 0, 3);
Call in fact in retrofit is the use of the network request and processing the return value of the class, calls will be required to join the parameters passed in, where the final URL to get the full address of

Https://api.douban.com/v2/book/search?q=%E5%B0%8F%E7%8E%8B%E5%AD%90&tag=&start=0&count=3

To complete a synchronous or asynchronous request using the call instance

Sync Request

Booksearchresponse response = Call.execute (). body ();
It is important to note that the network request must be done in the child thread, not directly on the UI thread, or it will crash

Asynchronous request

The code is as follows Copy Code

Call.enqueue (New callback<booksearchresponse> () {
@Override
public void Onresponse (call<booksearchresponse> call, response<booksearchresponse> Response) {
Asynctext.settext ("Asynchronous request Result:" + response.body (). Books.get (0). Alttitle);
}
@Override
public void OnFailure (call<booksearchresponse> call, Throwable t) {

}
});

Second, how to use

First you need to introduce the required third package in the Build.gradle file, configured as follows:

The code is as follows Copy Code
Compile ' com.squareup.retrofit2:retrofit:2.1.0 '
Compile ' com.squareup.retrofit2:converter-gson:2.1.0 '
Compile ' com.squareup.retrofit2:adapter-rxjava:2.1.0 '

After the introduction of the third package you can then use retrofit to make network requests. The next step is to make a further explanation of the different request methods.

Get method

1. @Query

The Get method request parameters are key=value to the URL, and retrofit provides two ways to set the request parameters. The first is to add @query annotations directly to the interface as mentioned above, and there is a way to do this through interceptor, directly looking at how the request parameter can be added through interceptor.

  code is as follows copy code
public class Custominterceptor implements Interceptor {
    @Override
    public Response Intercept (Chain Chain) throws IOException {
        request request = Chain.request ();
        Httpurl httpurl = Request.url (). Newbuilder ()
                 Addqueryparameter ("token", "Tokenvalue ")
                build ();
        request = Request.newbuilder (). URL (httpurl). build ();
        return chain.proceed (Request);
   }
}

Addqueryparameter is the specific code to add request parameters, this method is more suitable for all requests that need to be added to the parameters, generally the current network request will add token as the user identity, then this approach is more appropriate.

After you create a custom interceptor, you also need to create a client at retrofit to complete the add

The code is as follows Copy Code
Addinterceptor (New Custominterceptor ())

2. @QueryMap

If there are more query parameters, you can integrate all the parameters into a map in a @querymap way, and the GET request method in the above article as an example

The code is as follows Copy Code
Public interface Blueservice {
@GET ("Book/search")
Call<booksearchresponse> getsearchbooks (@QueryMap map<string, string> options);
}

When called, all parameters are assembled in a unified map.

The code is as follows Copy Code
map<string, string> options = new hashmap<> ();
Map.put ("Q", "Little Prince");
Map.put ("tag", null);
Map.put ("Start", "0");
Map.put ("Count", "3");
Call<booksearchresponse> call = Mblueservice.getsearchbooks (options);

3. Query Collection

If you need to add the same key value, but the value has more than one case, one way is to add multiple @query parameters, there is an easy way is to put all the value in the list, and then complete the add under the same @query, the instance code is as follows:

The code is as follows Copy Code
Public interface Blueservice {
@GET ("Book/search")
Call<booksearchresponse> Getsearchbooks (@Query ("q") list<string> name);
}

The resulting URL address is

Https://api.douban.com/v2/book/search?q=leadership&q=beyond%20feelings
4. Query is not required

If the request parameter is not required, which means that the server can parse correctly even if the parameter is not passed, how do you implement it? In fact, it is also very simple, the request method definition or need a complete query annotation, a request if you do not need to pass the argument, just fill in null.

For a request to the get that is mentioned at the beginning of the article, the join is called in the following manner

Call<booksearchresponse> call = Mblueservice.getsearchbooks ("The Little Prince", NULL, 0, 3);
The resulting URL address is

Https://api.douban.com/v2/book/search?q=%E5%B0%8F%E7%8E%8B%E5%AD%90&start=0&count=3
5. @Path

If the requested relative address is also required to be passed by the caller, you can use the @path annotation, the sample code is as follows:

@GET ("Book/{id}")
Call<bookresponse> GetBook (@Path ("id") String ID);
The business side wants to splice the book ID behind the address, then the path annotation can be dynamically passed in the specific invocation scenario, and the specific invocation method is as follows:

Call<bookresponse> call = Mblueservice.getbook ("1003078");
At this point the URL address is

https://api.douban.com/v2/book/1003078
@Path can be used for any type of request, including Post,put,delete, etc.

POST request

1. @field

Post requests need to place the request parameters in the request body, rather than stitching it behind the URL, to see a simple example

The code is as follows Copy Code
@FormUrlEncoded
@POST ("Book/reviews")
Call<string> addreviews (@Field ("book") string BookID, @Field ("title") string title,
@Field ("content") string content, @Field ("rating") string rating);

Here are a few things to explain.

@FormUrlEncoded will automatically adjust the type of the request parameter to application/x-www-form-urlencoded, and if the content passes a parameter of good Luck, the final request is

Content=good+luck
Formurlencoded cannot be used for GET requests

@Field Note holds each request parameter to the request body, and you can add the encoded parameter, which is Boolean, and the specific usage is

@Field (value = "book", encoded = True) String Book
If the encoded parameter is true, the Key-value-pair will be encoded to encode the Chinese and special characters for conversion

2. @FieldMap

The above POST request has 4 request parameters, if there are more request parameters, then pass one of the parameters are cumbersome and error-prone, this time can be used Fieldmap

The code is as follows Copy Code
@FormUrlEncoded
@POST ("Book/reviews")
Call<string> addreviews (@FieldMap map<string, string> fields);

3. @Body

If there are multiple POST request parameters, it should be better to unify the package into the class, which is very convenient to maintain

The code is as follows Copy Code

@FormUrlEncoded
@POST ("Book/reviews")
Call<string> Addreviews (@Body reviews reviews);

public class Reviews {
Public String Book;
Public String title;
public String content;
public String rating;
}

Other Request methods

In addition to get and post requests, HTTP requests include put,delete and so on, which are similar to post, so they are not introduced separately.

Upload

Upload because need to use multipart, so need to take out a separate introduction, first look at a specific upload example

First, you need to create a new interface to define the upload method.

The code is as follows Copy Code

Public interface Fileuploadservice {
Upload a single file
@Multipart
@POST ("Upload")
Call<responsebody> UploadFile (
@Part ("description") requestbody description,
@Part multipartbody.part file);

Upload Multiple Files
@Multipart
@POST ("Upload")
Call<responsebody> Uploadmultiplefiles (
@Part ("description") requestbody description,
@Part Multipartbody.part File1,
@Part Multipartbody.part file2);
}

Next we need to implement two tool methods in the activity and fragment, the following code:

The code is as follows Copy Code

public static final String multipart_form_data = "Multipart/form-data";

@NonNull
Private Requestbody createpartfromstring (String descriptionstring) {
Return Requestbody.create (
Mediatype.parse (Multipart_form_data), descriptionstring);
}

@NonNull
Private Multipartbody.part Preparefilepart (String partname, Uri Fileuri) {
File File = Fileutils.getfile (this, Fileuri);

Create a Requestbody instance for file
Requestbody RequestFile =
Requestbody.create (Mediatype.parse (multipart_form_data), file);

Multipartbody.part to complete the final upload with the help of filename
Return MultipartBody.Part.createFormData (PartName, File.getname (), requestfile);
}

Okay, so here's the final upload file code.

The code is as follows Copy Code

Uri File1uri = ...//get from file selector or camera
Uri File2uri = ...

Create an uploaded service instance
Fileuploadservice Service =
Servicegenerator.createservice (Fileuploadservice.class);

Create the part of the file (photo, video, ...)
Multipartbody.part body1 = Preparefilepart ("video", File1uri);
Multipartbody.part body2 = Preparefilepart ("thumbnail", File2uri);

Add additional part
Requestbody Description = createpartfromstring ("Hello, this is description speaking");

The last asynchronous request operation is performed
Call<responsebody> call = Service.uploadmultiplefiles (description, body1, body2);
Call.enqueue (New callback<responsebody> () {
@Override
public void Onresponse (call<responsebody> call,
Response<responsebody> Response) {
LOG.V ("Upload", "success");
}
@Override
public void OnFailure (call<responsebody> call, Throwable t) {
LOG.E ("Upload error:", T.getmessage ());
}
});

Iii. Other matters that must be known

1. Add a custom header

Retrofit provides two ways to define HTTP request header parameters: Static methods and dynamic methods, static methods cannot vary with different requests, and header information is fixed at initialization time. Dynamic methods, however, must be set separately for each request.

static method

The code is as follows Copy Code
Public interface Blueservice {
@Headers ("cache-control:max-age=640000")
@GET ("Book/search")
Call<booksearchresponse> Getsearchbooks (@Query ("q") String name,
@Query ("tag") String tag, @Query ("start") int start,
@Query ("Count") int count);
}

Of course you want to add multiple header parameters is also OK, the writing is very simple

The code is as follows Copy Code
Public interface Blueservice {
@Headers ({
"Accept:application/vnd.yourapi.v1.full+json",
"User-agent:your-app-name"
})
@GET ("Book/search")
Call<booksearchresponse> Getsearchbooks (@Query ("q") String name,
@Query ("tag") String tag, @Query ("start") int start,
@Query ("Count") int count);
}

In addition, you can define a static request header by interceptor.

  code is as follows copy code
public class Requestinterceptor implements Interceptor {
    @Override
    public Response Intercept (Chain Chain) throws IOException {
        Request original = Chain.request ();
        Request request = Original.newbuilder ()
             header ("User-agent", "Your-app-name")
             header ("Accept", "Application/vnd.yourapi.v1.full+json")
             Method (Original.method (), Original.body ())
            build ();
        return chain.proceed (Request);
   }
}

Add header parameter request provides two methods, one is header (key, value), and the other is. AddHeader (key, value), the difference is that header () if there is a duplicate will be overwritten, and AddHeader () Allow header existence of same key value

Then, when Okhttp creates a client instance, add Requestinterceptor

The code is as follows Copy Code
private static Okhttpclient getnewclient () {
return new Okhttpclient.builder ()
. Addinterceptor (New Requestinterceptor ())
. ConnectTimeout (Default_timeout, Timeunit.seconds)
. build ();
}

Dynamic method

The code is as follows Copy Code

Public interface Blueservice {
@GET ("Book/search")
Call<booksearchresponse> Getsearchbooks (
@Header ("Content-range") String Contentrange,
@Query ("q") string name, @Query ("tag") string tag,
@Query ("start") int start, @Query ("Count") int count);
}

2. Network Request log

When debugging a network request, you often need to focus on the request parameters and return values in order to determine and locate the problem, retrofit official provides a very easy to view the log interceptor, you can control the type of printing information you need, the use of the method is simple.

First you need to introduce logging-interceptor in the Build.gradle file.

Compile ' com.squareup.okhttp3:logging-interceptor:3.4.1 '
Like the Custominterceptor and requestinterceptor mentioned above, add to the okhttpclient creation, complete the sample code as follows:

  code is as follows copy code
private static okhttpclient getnewclient () {
    Httplogginginterceptor logging = new Httplogginginterceptor ();
    Logging.setlevel (HttpLoggingInterceptor.Level.BODY);
    return new Okhttpclient.builder ()
            Addinterceptor (New Custominterceptor ())
            Addinterceptor (logging)
           connecttimeout ( Default_timeout, Timeunit.seconds)
           build ();
}

Httplogginginterceptor provides 4 levels of control of the type of print information, respectively, None,basic,headers,body, followed by the corresponding type of printing information.

NONE

No log information

Basic

Print request type, URL, request body size, return value status, and return value size

D/httplogginginterceptor$logger:--> post/upload http/1.1 (277-byte body)
D/httplogginginterceptor$logger: <--http/1.1 OK (543ms, -1-byte body)
Headers

Print header information for return request and return values, request type, URL, and return value status code

The code is as follows Copy Code

<--OK https://api.douban.com/v2/book/search?q=%e5%b0%8f%e7%8e%8b%e5%ad%90&start=0&count=3& Token=tokenvalue (3787MS)
D/okhttp:date:sat, Aug 2016 14:26:03 GMT
D/okhttp:content-type:application/json; Charset=utf-8
D/okhttp:transfer-encoding:chunked
D/okhttp:connection:keep-alive
D/okhttp:keep-alive:timeout=30
D/okhttp:vary:accept-encoding
D/okhttp:expires:sun, 1 2006 01:00:00 GMT
D/okhttp:pragma:no-cache
D/okhttp:cache-control:must-revalidate, No-cache, private
D/OKHTTP:SET-COOKIE:BID=D6UTQR5N9I4; Expires=sun, 06-aug-17 14:26:03 GMT; domain=.douban.com; path=/
D/okhttp:x-douban-newbid:d6utqr5n9i4
D/okhttp:x-dae-node:dis17
D/okhttp:x-dae-app:book
D/okhttp:server:dae
D/okhttp: <--End HTTP
Body

Print the header and body information for the request and return values

&lt;--OK https://api.douban.com/v2/book/search?q=%E5%B0%8F%E7%8E%8B%E5%AD%90&amp;tag=&amp;start=0&amp;count= 3&amp;token=tokenvalue (3583MS)


D/okhttp:connection:keep-alive


D/okhttp:date:sat, Aug 2016 14:29:11 GMT


D/okhttp:keep-alive:timeout=30


D/okhttp:content-type:application/json; Charset=utf-8


D/okhttp:vary:accept-encoding


D/okhttp:expires:sun, 1 2006 01:00:00 GMT


D/okhttp:transfer-encoding:chunked


D/okhttp:pragma:no-cache


D/okhttp:connection:keep-alive


D/okhttp:cache-control:must-revalidate, No-cache, private


D/okhttp:keep-alive:timeout=30


D/okhttp:set-cookie:bid=esnahto1_os; Expires=sun, 06-aug-17 14:29:11 GMT; domain=.douban.com; path=/


D/okhttp:vary:accept-encoding


D/okhttp:x-douban-newbid:esnahto1_os


D/okhttp:expires:sun, 1 2006 01:00:00 GMT


D/okhttp:x-dae-node:dis5


D/okhttp:pragma:no-cache


D/okhttp:x-dae-app:book


D/okhttp:cache-control:must-revalidate, No-cache, private


D/okhttp:server:dae


D/okhttp:set-cookie:bid=5qefvyuz3ku; Expires=sun, 06-aug-17 14:29:11 GMT; domain=.douban.com; path=/


D/okhttp:x-douban-newbid:5qefvyuz3ku


D/okhttp:x-dae-node:dis17


D/okhttp:x-dae-app:book


D/okhttp:server:dae


D/okhttp: {"Count": 3, "Start": 0, "Total": 778, "books": [{"rating": {"Max": "Numraters": 202900, "average": "9.0", "min ": 0}," subtitle ":" "," Author ": [" [FA] Saint Exupery "]," pubdate ":" 2003-8 "," tags ": [{" Count ": 49322," name ":" The Little Prince "," title ":" The Little Prince " },{"Count": 41381, "name": "Fairy Tale", "title": "Fairy Tale"},{"Count": 19773, "name": "Saint Exupery", "title": "Saint Exupery"}


D/okhttp: &lt;--End HTTP (13758-byte)

3. Set the full URL for a request

What if one of your requests does not begin with Base_url? Don't worry, the way is simple, look at the example below you can understand

The code is as follows Copy Code

Public interface Blueservice {
@GET
Public call<responsebody> profilepicture (@Url String Url);
}

Retrofit RETROFIT = Retrofit.builder ()
. BaseURL ("https://your.api.url/");
. build ();

Blueservice service = retrofit.create (Blueservice.class);
Service.profilepicture ("Https://s3.amazon.com/profile-picture/path");

The complete URL address can be passed directly in the form of a @url annotation.

4. Cancel Request

Call provides the Cancel method to cancel the request if the request has not yet been executed

The code is as follows Copy Code

String fileUrl = "Http://futurestud.io/test.mp4";
Call<responsebody> call =
Downloadservice.downloadfilewithdynamicurlsync (FILEURL);
Call.enqueue (New callback<responsebody> () {
@Override
public void Onresponse (call<responsebody> call, response<responsebody> Response) {
LOG.D (TAG, "request Success");
}

@Override
public void OnFailure (call<responsebody> call, Throwable t) {
if (call.iscanceled ()) {
LOG.E (TAG, "request was cancelled");
} else {
LOG.E (TAG, "other larger issue, i.e. no network connection?");
}
}
});
}

Triggers an action, such as a button that the user clicked to cancel the request
Call.cancel ();
}

Four, the conclusion

About retrofit commonly used methods have been introduced, and some requests due to the confidentiality of work, so there is no release, but the basic methods and operations are there, in the text mentioned in the code can achieve the function you want

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.