Retrofit2 目前最优雅的网络请求框架
DeclanVIEA
8年前
<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>