Retrofit的讲解和使用
Retrofit适用于Android和Java的类型安全的HTTP客户端声明API接口方法及参数的注解用于控制一个请求.请求方法每一个方法必须带有一个HTTP注解, 用于提供相应的请求方法和URL. 目前有5种内置的注解: GET , POST , PUT , DELETE和 HEAD . 注解中指定了相应的URL.@GET("users/list")您还可以指定U
Retrofit
适用于Android和Java的类型安全的HTTP客户端
声明API
接口方法及参数的注解用于控制一个请求.
请求方法
每一个方法必须带有一个HTTP注解, 用于提供相应的请求方法和URL. 目前有5种内置的注解: GET , POST , PUT , DELETE和 HEAD . 注解中指定了相应的URL.
@GET("users/list")
您还可以指定URL中的查询参数.
@GET("users/list?sort=desc")
操作URL
请求URL可以使用方法中的替换块和参数进行动态替换. 替换块是指由 { 和 } 包裹的字符串. 其对应的参数必须使用相同的字符串,并使用 @Path 进行注解.
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);
查询参数同样可以动态添加.
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
对于复杂的查询参数组合, 可以使用 Map .
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String>
请求体
可以使用 @Body 注解来指定一个对象作为HTTP请求体.
@POST("users/new")
Call<User> createUser(@Body User user);
该对象同时也会被 Retrofit 实例所指定的转化器所转化. 如果没有添加转化器,则只有 RequestBody 可以被使用.
编码表单和分段数据
方法也可以被声明为发送编码表单和分段数据.
当使用 @FormUrlEncoded 注解方法时, 则为发送编码表单数据.每个键值对使用 @Field 注解, 并在其中带有名称和提供值的对象.
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name")当使用 @Multipart 注解方法时, 则为分段请求.每段数据使用 @Part 注解来声明.
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description")分段数据需要使用 Retrofit 中的某个转化器,或者通过实现 RequestBody 来处理分段数据的序列化.
操作请求头
您可以使用 @Headers 注解为一个方法设置静态的请求头.
@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);
注意, 请求头不会相互覆盖. 所有同名的请求头都会包含在请求中.
可以使用 @Header 注解来动态更新请求头.并且必须向 @Header 提供相应的参数. 如果参数值为空, 则该请求头将会被忽略. 如果参数值不为空,则会调用该值的 toString 并使用其结果.
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)
对于所有请求都需要添加的请求头, 可以使用OkHttp interceptor来指定.
同步和异步
Call 实例既可以同步执行, 也可以异步执行. 每个实例只能被使用一次, 但通过调用 clone() 可以创建一个新的实例.
在Android中, 回调将会在主线程中执行. 在JVM中, 回调将发生在执行HTTP请求的线程中.
配置Retrofit
Retrofit 是一个将API接口转化为可调用对象的类. 默认情况下, Retrofit提供了默认的配置, 但他也允许进行自定义.
转化器
默认情况下, Retrofit只能将HTTP请求体反序列化为OkHttp的 ResponseBody 类型,
并且在 @Body中只能接受 RequestBody 类型.
可以添加转化器以便支持其他类型. 为了您的使用便捷, 已经有6种模块适配了流行的序列化库.
Gson: com.squareup.retrofit2:converter-gson
Jackson: com.squareup.retrofit2:converter-jackson
Moshi: com.squareup.retrofit2:converter-moshi
Protobuf: com.squareup.retrofit2:converter-protobuf
Wire: com.squareup.retrofit2:converter-wire
Simple XML: com.squareup.retrofit2:converter-simplexml
Scalars (primitives, boxed, and String): com.squareup.retrofit2:converterscalars
以下是使用 GsonConverterFactory 类生成一个使用Gson进行反序列化
的 GitHubService 接口实现类的示例.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHubService service = retrofit.create(GitHubService.class);
自定义转化器
如果您需要使用Retrofit不支持的内容格式(如YAML, txt, 自定义格式)与API进行通信, 或者您希望使用不同的库实现已有的格式, 您可以简单地创建自定义转化器.创建一个类继承 Converter.Factory 类, 并在创建适配器时传入一个实例即可.
下载
Retrofit源码, 示例和网站可在GitHub上获取.
https://github.com/square/retrofit
依赖:
compile'com.squareup.retrofit2:retrofit:2.2.0'
混淆
如果您在项目中使用混淆, 请添加以下代码到混淆配置中:
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
做了个一个小案例先看一下App展示:
直接看代码:
public interface IService { /** * 每个方法必须有一个HTTP请求注释提供请求方法和相对URL。 * 有五个内置注释:GET、POST、PUT、DELETE、HEAD。 * 注解中指定资源的相对URL * (说白了,就是除了Url根目录外的子目录, * 比如:https://www.baidu.com/?tn=22073068_oem_dg * 中,https://www.baidu.com为根目录, * 后面的这一串:/?tn=22073068_oem_dg就是子目录,也就是需要在注解中写入的相对URL)。 */ @GET("/test/test.json") /** * FruitData 为javabean对象 * getList(),该方法名字随便起 * @Query("title") String title 就是通过Query注解来查询title字段 */ Call<FruitData> getList(@Query("title") String title); }
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyHolder> { private Context mContext; private ArrayList<FruitData.FruitName> mDatas; public MyAdapter(Context context, ArrayList<FruitData.FruitName> data) { this.mContext = context; this.mDatas = data; } @Override public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(mContext); View view = inflater.inflate(R.layout.layout_recyclerview, parent, false); MyHolder holder = new MyHolder(view); return holder; } @Override public void onBindViewHolder(MyHolder holder, int position) { holder.tvTitle.setText(mDatas.get(position).title); } @Override public int getItemCount() { return mDatas.size(); } class MyHolder extends RecyclerView.ViewHolder { TextView tvTitle; public MyHolder(View itemView) { super(itemView); tvTitle = (TextView) itemView.findViewById(R.id.tvTitle); } } }
public class MainActivity extends AppCompatActivity { private Button btnRetrofit; private RecyclerView recyclerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { btnRetrofit = (Button) findViewById(R.id.btn_retrofit); recyclerView = (RecyclerView) findViewById(R.id.recyclerview); recyclerView.setLayoutManager(new LinearLayoutManager(this)); btnRetrofit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { useRetroift(); } }); } private void useRetroift() { //获取Retrofit实例对象 Retrofit retrofit = new Retrofit.Builder() //Url根目录 .baseUrl("http://192.168.1.101:8080") //增减转换工厂(创建Gson转换工厂) .addConverterFactory(GsonConverterFactory.create()) .build(); //获取接口对象 IService iService = retrofit.create(IService.class); //获取Call对象 Call<FruitData> call = iService.getList("title"); //调用Call的异步网络请求方法 call.enqueue(new Callback<FruitData>() { @Override //请求成功,并获取到json解析后的数据 public void onResponse(Call<FruitData> call, Response<FruitData> response) { ArrayList<FruitData.FruitName> data = response.body().data; recyclerView.setAdapter(new MyAdapter(MainActivity.this, data)); } @Override public void onFailure(Call<FruitData> call, Throwable t) { } }); } }
public class FruitData { public ArrayList<FruitName> data; public class FruitName { public String title; } }
更多推荐
所有评论(0)