Retrofit2 目前最优雅的网络请求框架

DeclanVIEA 7年前
   <p>身为Geek的我们,面对不断更新换代的技术是不是有点感到迷茫呢?其实只要掌握正确的学习方法,新的技术也就不畏惧了。</p>    <p>正是面哥的鞭策,我决定开始看英文的技术文档,学习新技术也是直接看官网的技术文档,本篇文章就是我在Retrofit2的官网看完英文文档 Retrofit 以及参考多篇博文之后总结出来的。</p>    <h2>Retrofit</h2>    <p>Retrofit</p>    <p>是一个Square开发的类型安全的REST 安卓 客户端请求库。这个库为网络认证、API请求以及用OkHttp发送网络请求提供了强大的框架 。</p>    <p>Retrofit 把REST API返回的数据转化为 Java 对象,就像ORM框架那样,把 数据库 内的存储的数据转化为相应的Java</p>    <p>bean对象。 那么我们知道Retrofit是一个类型安全的网络框架,而且它是使用REST API的.</p>    <h2>REST :</h2>    <p>Resources Representational State Transfer</p>    <p>资源表现层状态转化 每一个URI代表一种资源</p>    <p>客户端和服务器之间,传递这种资源的某种 表现层(“资源”具体呈现出来的形式,比如.txt,.png,.jpg)</p>    <p>客户端通过四个HTTP动词(GET用来获取资源,POST用来新建或更新资源,PUT用来更新资源,DELETE用来删除资源)对服务器端资源进行操作,实现”表现层状态转化”</p>    <h2>Retrofit的简单使用</h2>    <p>这里使用官方的例子介绍,也是以github的api做 <a href="/misc/goto?guid=4959733742320181123" rel="nofollow,noindex">测试</a></p>    <h2>第零步:</h2>    <p>添加依赖:</p>    <pre>  <code class="language-java">//okHttp      compile 'com.squareup.okhttp3:okhttp:3.2.0'  //retrofit      compile 'com.squareup.retrofit2:retrofit:2.0.2'      compile 'com.squareup.retrofit2:converter-gson:2.0.2'      compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'</code></pre>    <p>准备api接口:</p>    <p><a href="/misc/goto?guid=4959742120100020722" rel="nofollow,noindex">https://api.github.com/users/wu-leaf/repos</a></p>    <p>需要封装的javabean 类</p>    <p>其中我抽取出用来测试的属性如下4个:</p>    <pre>  <code class="language-java">public class Repo {      private int id;      private String name;      private String full_name;      private String fork;        //get\set方法</code></pre>    <h2>第一步:</h2>    <p>改造你的HTTP API变成一个Java接口。</p>    <pre>  <code class="language-java">public interface GitHubService {    @GET("users/{user}/repos")    Call<List<Repo>> listRepos(@Path("user") String user);  }</code></pre>    <h2>第二步:</h2>    <p>Retrofit 生成一个GitHubService 接口的实现</p>    <pre>  <code class="language-java">Retrofit retrofit = new Retrofit.Builder()      .baseUrl("https://api.github.com/")      .build();    GitHubService service = retrofit.create(GitHubService.class);</code></pre>    <p>来自创建的GitHubService的每个调用都可以向远程Web服务器发出同步或异步HTTP请求。</p>    <pre>  <code class="language-java">Call<List<Repo>> repos = service.listRepos("wu-leaf");</code></pre>    <h2>第三步:</h2>    <p>异步调用</p>    <pre>  <code class="language-java">repos.enqueue(new Callback<List<Repo>>() {              @Override              public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {                  Log.d("TAG",response.body().toString());                  response_tv.setText(response.body().toString());              }                @Override              public void onFailure(Call<List<Repo>> call, Throwable t) {                   if (call.isCanceled()){                       Log.d("TAG",t.toString());                   }else{                       Log.e("TAG",t.toString());                   }              }          });</code></pre>    <p>同步调用:</p>    <p>当然不能在主线程调用</p>    <pre>  <code class="language-java">Call<Repo> clone = repos.clone();        Response<Repo> response = clone.execute();      Repobody = response.body();</code></pre>    <p>这个例子是不是挺简单的,现在现在正式了解下常用api吧</p>    <h2>常用API介绍</h2>    <p>接口方法及其参数的注释指示如何处理请求。</p>    <h3>请求方法</h3>    <p>每个方法必须具有提供请求方法和相对URL的HTTP注释。 有五个内置注释:GET,POST,PUT,DELETE和HEAD。 资源的相对URL在注释中指定。</p>    <pre>  <code class="language-java">@GET("users/list")</code></pre>    <p>您还可以在URL中指定查询参数。</p>    <pre>  <code class="language-java">@GET("users/list?sort=desc")</code></pre>    <h3>URL 相关操作</h3>    <p>可以使用替换块(占位符)和方法上的参数动态更新请求URL。 替换块是由{and}包围母数字字符串。 相应的参数必须使用相同的字符串用@Path注释。</p>    <pre>  <code class="language-java">@GET("group/{id}/users")  Call<List<User>> groupList(@Path("id") int groupId);</code></pre>    <h3>也可以添加查询参数。</h3>    <pre>  <code class="language-java">@GET("group/{id}/users")  Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);</code></pre>    <h3>对于复杂的查询参数组合,可以使用Map。</h3>    <pre>  <code class="language-java">@GET("group/{id}/users")  Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);</code></pre>    <h3>请求体</h3>    <p>可以指定一个对象用作带有@Body注释的HTTP请求体。</p>    <pre>  <code class="language-java">@POST("users/new")  Call<User> createUser(@Body User user);</code></pre>    <p>该对象也将使用Retrofit实例上指定的转换器进行转换。 如果没有添加转换器,则只能使用RequestBody。</p>    <h3>提交表单和多部分数据</h3>    <p>方法也可以声明为发送提交表单和多部分数据。</p>    <p>当方法上存在@FormUrlEncoded时,将发送表单编码的数据。 每个键值对都使用包含名称的@Field和提供值的对象进行注释。</p>    <pre>  <code class="language-java">@FormUrlEncoded  @POST("user/edit")  Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);</code></pre>    <p>多部分请求时使用@Multipart存在的方法。部分使用@Part注释声明。</p>    <pre>  <code class="language-java">@Multipart  @PUT("user/photo")  Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);</code></pre>    <p>多部分使用Retrofit的转换器,或者它们可以实现RequestBody来处理自己的序列化。</p>    <h3>请求头操作</h3>    <p>您可以使用@Headers注释为方法设置静态头。</p>    <pre>  <code class="language-java">@Headers("Cache-Control: max-age=640000")  @GET("widget/list")  Call<List<Widget>> widgetList();  @Headers({      "Accept: application/vnd.github.v3.full+json",      "User-Agent: Retrofit-Sample-App"  })  @GET("users/{username}")  Call<User> getUser(@Path("username") String username);  </code></pre>    <p>请注意,请求头不会相互覆盖。 具有相同名称的所有请求头将包含在请求中。</p>    <p>请求头可以使用@Header注释动态更新。 必须向@Header提供相应的参数。 如果值为null,则将省略请求头。 否则,toString将被调用的值,并使用结果。</p>    <pre>  <code class="language-java">@GET("user")  Call<User> getUser(@Header("Authorization") String authorization)</code></pre>    <p>需要添加到每个请求的标头可以使用OkHttp拦截器指定。</p>    <h2>同步 vs 异步</h2>    <p>Call 实例可以同步或异步执行。 每个实例只能使用一次,但调用clone()将创建一个可以使用的新实例。</p>    <p>在 <a href="/misc/goto?guid=4959719078014872990" rel="nofollow,noindex">Android</a> 上,回调将在主线程上执行。 在JVM上,回调将发生在执行HTTP请求的同一线程上。</p>    <h2>Retrofit 配置</h2>    <p>Retrofit是将API接口转换为可调用对象的类。 默认情况下,Retrofit将为您的平台提供正常默认值,但它允许自定义。</p>    <h3>转换器:</h3>    <p>默认情况下,Retrofit只能将HTTP主体反序列化为OkHttp的ResponseBody类型,并且它只能接受@Body的RequestBody类型。</p>    <p>可以添加转换器以支持其他类型。 六个同级模块适应流行的序列化库为您方便使用。</p>    <p>- Gson: com.squareup.retrofit2:converter-gson</p>    <p>- Jackson: com.squareup.retrofit2:converter-jackson</p>    <p>- Moshi: com.squareup.retrofit2:converter-moshi</p>    <p>- Protobuf: com.squareup.retrofit2:converter-protobuf</p>    <p>- Wire: com.squareup.retrofit2:converter-wire</p>    <p>- Simple XML: com.squareup.retrofit2:converter-simplexml</p>    <p>- Scalars (primitives, boxed, and String):</p>    <p>- com.squareup.retrofit2:converter-scalars</p>    <p>下面是一个使用GsonConverterFactory类来生成GitHubService接口的实现的例子,它使用Gson进行反序列化。</p>    <pre>  <code class="language-java">Retrofit retrofit = new Retrofit.Builder()      .baseUrl("https://api.github.com")      .addConverterFactory(GsonConverterFactory.create())      .build();    GitHubService service = retrofit.create(GitHubService.class);</code></pre>    <h3>自定义转换器</h3>    <p>如果您需要与使用Retrofit不支持开箱即用的内容格式(例如YAML,txt,自定义格式)的API进行通信,或者希望使用其他库来实现现有格式,则可以轻松创建 你自己的转换器。 创建一个扩展Converter.Factory类的类,并在构建适配器时传递实例。</p>    <h3>依赖方式:</h3>    <p>MAVEN</p>    <pre>  <code class="language-java"><dependency>    <groupId>com.squareup.retrofit2</groupId>    <artifactId>retrofit</artifactId>    <version>2.2.0</version>  </dependency></code></pre>    <p>GRADLE</p>    <pre>  <code class="language-java">compile 'com.squareup.retrofit2:retrofit:2.0.2'      compile 'com.squareup.retrofit2:converter-gson:2.0.2'</code></pre>    <p>Retrofit需要至少 Java  7或Android 2.3。</p>    <h2>PROGUARD混淆</h2>    <p>如果在项目中使用Proguard,请在配置中添加以下行:</p>    <pre>  <code class="language-java"># Platform calls Class.forName on types which do not exist on Android to determine platform.  -dontnote retrofit2.Platform  # Platform used when running on RoboVM on iOS. Will not be used at runtime.  -dontnote retrofit2.Platform$IOS$MainThreadExecutor  # Platform used when running on Java 8 VMs. Will not be used at runtime.  -dontwarn retrofit2.Platform$Java8  # Retain generic type information for use by reflection by converters and adapters.  -keepattributes Signature  # Retain declared checked exceptions for use by a Proxy instance.  -keepattributes Exceptions</code></pre>    <p> </p>    <p> </p>    <p>来自:http://www.androidchina.net/6550.html</p>    <p> </p>