A brief analysis of Android's retrofit application Development Framework source code _android

Source: Internet
Author: User
Tags aop documentation function definition throwable

In the face of a project, I think of three options for Android application Development framework:
1. The use of loader + httpclient + Greendao + Gson + Fragment, the advantage is a strong customization, because of the use of Google's own loader and Loadermanager, strong code robustness.
The disadvantage is that the whole set of code learning costs are high, the use of the process Model code more, (for example, each request will need to produce a new class)
2.Volley, as Google in the IO Conference on a network library, in fact, nothing new (2013 IO release), the use of simpler, request can be canceled, can provide priority requests, looks good.
3.Retrofit, a rest API to make requests extremely simplistic, the voice is also very high, the use of the threshold is almost small white.
How do you choose? First Kill 1, because the cost of learning for new people is really too high, if you want to quickly develop a project, high learning costs are fatal, while using a lot of boilerplate code.

So how do you choose between volley and retrofit? Although there are many articles on the Internet to introduce the use of two frameworks, but for its principles, especially the comparative analysis of less, if you have a project, how to select the network module?
First, explain the level of the two network frameworks in the project:

As can be seen from the above figure, whether volley or retrofit, they are all the existing solutions are integrated, and provide a friendly, rapid development of the program, in the integration process, each module could be customized or replaced. such as deserialization of work, such as HttpClient.

And in this article we will briefly look at the retrofit source section.


Note that this article does not use the retrofit Help document, it is recommended that you look at the retrofit documentation and OKHTTP documentation first, which is important for understanding the rest of the section.

Send a request using retrofit
Let's say we're going to get the following JSON back from this address http://www.exm.com/search.json?key=retrofit:

 {"
  data": [
        {
         "title": "Retrofit Use profile",
         "desc": "Retrofit is a httpclient for Android and Java", "
         link" : "Http://www.exm.com/retrofit"
        },
        {
         "title": "Retrofit Use profile",
         "desc": " Retrofit is a httpclient for Android and Java, "
         link": "Http://www.exm.com/retrofit"
        },
        {
         "title": " Retrofit use Introduction ",
         " desc ":" Retrofit is a httpclient for Android and Java ","
         link ":" Http://www.exm.com/retrofit "
        } 
     ]
 }

1. Introducing Reliance

Compile ' com.squareup.retrofit:retrofit:2.0.0-beta2 '
//gson parsing
compile ' com.squareup.retrofit: Converter-gson:2.0.0-beta2 '

2. Configure Retrofit

Retrofit RETROFIT = new Retrofit.builder ()
          . BaseURL ("http://www.exm.com")
          . Addconverterfactory ( Gsonconverterfactory.create ())
          . Client (new Okhttpclient ())
          . Build ();

3. New Model class SearchResult to resolve results

4. New Request Interface
Retrofit uses annotations to define a request, to specify information such as the requested method on the method, and to specify parameters in the parameters.

Public interface Restapi {
    @GET ("/search.json")
    call<list<searchresult>> Search (
      @Query (" Key ") String key
       );

      You can define other request
      @GET ("/something.json")
      call<something> dosomething (
          @Query ("params") long params
          .......
          .......
       );

}

5. To send a request, we can send a sync request (blocking the current thread) and an asynchronous request, and process the request result in the callback.

 Restapi Restapi = retrofit.create (restapi.class);
 call<list<searchresult>> Searchresultscall = Resetapi.search ("retrofit");
 Response<list<searchresult> searchresults = Searchresultscall.execute ();  Synchronization method
 Searchresultscall.enqueue (new callback<list<searchresult>> () {
        @Override public
        Void Onresponse (response<list<searchresult>> Response, retrofit retrofit) {
          Content.settext ( Response.body (). toString ());

        @Override public
        void OnFailure (Throwable t) {
          content.settext ("error");
        }
      );

Retrofit Source Analysis
retrofit the entire project using dynamic agents and static agents, if you are not very clear agent mode, suggest that Google first, if the dynamic agent for Java is not too familiar with the principle, strongly recommend to see first: This article-play said agent and Java dynamic Agent
OK, follow the steps we use to send the request retrofit:

Restapi Restapi = retrofit.create (restapi.class);  To produce an RESTAPI instance

Enter an interface to output an instance directly.

Here, a word, now casually search Baidu on the Java dynamic Proxy, out a bunch of introduction of AOP (aspect-oriented programming) and spring, causing some people to the cart before the horse, that the dynamic agent is almost equal to AOP, and even some people think that dynamic agent is specialized in a function before and after the execution of an action to add , such as statistical time (since almost all places where dynamic proxies are present), Hairenbujian. In fact, dynamic Proxy is the JDK provided by the API, not by these superstructure, it can do a lot of other things, retrofit in the use of dynamic agents is supporting.
Take a look at the source here, again, if the code here does not understand, first look at the above mentioned article:

 public <T> T Create (final class<t> service) {//Returns an instance of a dynamic proxy class return (T) Pr Oxy.newproxyinstance (Service.getclassloader (), new class<?>[] {service},//This invocationhandler is the key,

   Subsequent calls to the Restapi interface will be sent here to New Invocationhandler () {private final Platform Platform = Platform.get (); @Override public Object Invoke (object proxy, Method method, Object ... args) throws Throwable {/* If the side of object method, such as ToString (), directly calls the Invocationhandler method, * Note that there is actually no meaning here, because Invocationhandler is actually a command transporter * In dynamic proxies, these methods are not semantically, so do not
    Need Care * * (method.getdeclaringclass () = = Object.class) {return Method.invoke (this, args); ///For JAVA8 compatibility, there is no need to consider if (Platform.isdefaultmethod) {return Platform.invokedefaultmethod (Met) in Android
    Hod, service, proxy, args);
   //Returns a Call object return Loadmethodhandler (method). Invoke (args);
} 
  }); }

We can see Retrofit.create () After returning an instance of the dynamic proxy class for an interface, so when we call the method of the proxy class, the call is naturally sent to our defined Invocationhandler, so call

 
 

, the Invoke method to the Invocationhandler is called directly, and the following is the context of invoke at this time:

  @Override Public 
   object Invoke (Object proxy, Method method, Object ... args)
     throws Throwable {
     // The proxy object is the Resetapi object that you call the method outside
     //method is the function definition in Restapi, so
     we can get the annotations defined on functions and parameters, such as the parameter//args in @get and annotations
     , Actual parameters, where the transmission is the string "retrofit"

    //Here must be return a Call object return
    Loadmethodhandler (method). Invoke (args);
   }

At this point, the return of Invoke must be a call,call is retrofit in the abstract of a request, thus, we should not be difficult to imagine Loadmethodhandler (method). Invoke (args); This code should be to parse the interface to pass in the annotation, and generate a okhttpclient in the corresponding request, so we call Searchresultscall, call okhttpclient go network. Indeed, the main melody of retrofit is indeed such a drop.

Note that in fact Call,callback this description is introduced in okhttp, retrofit the underlying use of okhttp so it is also using these two class names to abstract a network request and a callback after a request is returned. Overall, the call Callback in retrofit holds a okhttp called Callback that forwards the various calls in retrofit to the Okhttp class library, which is actually a static proxy, because we define the various proxy classes, Like Okhttpcall.

Note If there is no explicit expenditure, then all the call,callback are in the retrofit class
Methodhandler Class
Methodhandler class, which is the most important abstraction in the retrofit, each methodhandler corresponds to the request of each method representative in the RESTAPI of this example and the other configuration associated with this request, let's take a look.

This okhttp factory, used to produce a call in a Okhttp class library, is actually the okhttpclient private final OKHTTP3 of the incoming configuration builder
. Call.factory callfactory;
Through the annotation in method and the incoming parameter, form a okhttp request
private final requestfactory requestfactory;
For the retrofit in the call Agent
private final calladapter<?> calladapter;
For deserialization return results
private final converter<responsebody,?> Responseconverter;

Returns a Call object
invoke (Object ... args) {return calladapter.adapt ( 
  the new okhttpcall<> callfactory, Requestfactory, args, responseconverter));


In retrofit, the data encoding and parsing of the request and response are added to the retrofit by adding converter.factory. So we can add multiple converter.factory to provide retrofit with the ability to handle different data.

Calladapter can proxy the execution of call, which is a static proxy. We can also do some things by adding our own calladapter, such as caching the request:

 New Calladapter.factory {
   @Override public 
    <R> call<r> adapt (call<r> call) {return call;}

class Cachecall implements call {call
  delegate;
   Cachecall (call call) {
     this.delegate = call;
  }

  @Override public
  void Enqueue (callback<t> Callback) {
    //See if there is a cache, otherwise go directly to the network
    if (cached) {
      return cache;
    }
    This.delegate.enqueue (callback);
  }


At this point, when we call Resetapi.search ("retrofit"), the okhttpcall that is actually invoked after the layer proxy is called, and it is plugged in when invoke in the Methodhandler. Look at the code in Okhttpcall:

 @Override public void Enqueue (final callback<t> Callback) {okhttp3.
 Call Rawcall;
 try {//Create a okhttp call Rawcall = Createrawcall ();
  catch (Throwable t) {callback.onfailure (t);
 Return //Direct call to Okhttp's join Operation Rawcall.enqueue (new OKHTTP3.
  Callback () {private void Callfailure (Throwable e) {try {callback.onfailure (e);
  catch (Throwable t) {t.printstacktrace ();
  } private void Callsuccess (response<t> Response) {try {callback.onresponse (Response);
  catch (Throwable t) {t.printstacktrace ();
 @Override public void OnFailure (Request request, IOException e) {callfailure (e); @Override public void Onresponse (OKHTTP3.
  Response rawresponse) {response<t> Response;
  try {//Parse result response = Parseresponse (rawresponse);
   catch (Throwable e) {callfailure (e);
  Return
 } callsuccess (response);
}
}); }

As a result, Okhttpclient's callback has been directed to our callback, and the whole process has gone through.

Summarize
finally to the conclusion of the time, generally speaking, this is dry goods, haha ~

Volley comparative advantage
1. cache handling; Volley itself provides a complete cache processing scheme, which is stored on disk by default, and provides a mechanism for TTL softttl so considerate; One request may have two response, for the need to display caching, Display the network data again the scene is really cool don't want to. The retrofit does not provide any caching-related scenarios.
2. Simple code, high readability. Volley code is written so directly when you look at the code does not need a sip of tea, the advantage is that we need to modify the code is not easy to introduce bugs .... 囧
If the same request is being sent at the same time, then there is actually only one request that is really sent out, and the other requests will wait for the result to come back and be a little optimized. Actually this kind of scene is not many ha, if has, possibly is your code to have the problem ...
Requests are sent with a priority concept, but are guaranteed to go out only in order, not guaranteed in order to come back, and then the eggs.
Support for different HTTP client implementations, which provide the implementation of HttpClient and httpurlconnection by default, and retrofit after the 2.0 version, Locked to death on Okhttp.
3. Support Request Cancellation
Retrofit
1. Send a request is really simple, define a method on it, such a simple request framework who else? Volley?
2. Better scalability, each new request in the volley need to specify a parent class, tell the way the serialization of data, and retrofit only need to be configured, specify a variety of converters. The existence of calladapter, can make you arbitrary proxy call, good good ...
3.OkHttpClient comes with a concurrent halo, and the worker threads in the volley are maintained by themselves, then there is a risk that the thread will not be replenished by the next worker thread because of an abnormal exit (the thread pool can compensate for this defect), which does not exist in the retrofit, because even if there is a problem , this pot will also throw to Okhttp, hehe
4. Support Request Cancellation

Again, retrofit does not provide any additional support for caching, which means it can only be stored through the cache control of HTTP, so there are some problems:
1. The server needs to control the cache through the head of cache controls, need to modify the background code
2. Some places are more suitable to use the database to store, for instance the relational storage, at this time, retrofit can not be helpless
3. The cache is not within our control, but completely through the okhttp to manage, some inconvenience, such as we want to delete a specified cache, or update a specified cache, the code is very awkward to write (oneself hack request head inside the cache Contrl)

In our project in the actual use of the process, caching is a relatively important role, retrofit cache support is not very good, really sad ...
However, we still feel that in the use of retrofit sincerely more convenient, easy to start, through the annotation code readability and maintainability to improve the n grade, almost no boilerplate code (well, if you think each request needs to define a method, it is also counted.) ), so the final decision is to choose retrofit.

It's been said that two responses and caches in volley are happy. Well, we will modify the retrofit, so that it supports file storage and ORM storage, and the volley cache network two response callback to take over, this project is testing phase, to our project to finish the mouse, on line stability, I will be the code open source, we stay tuned.

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.