Retrofit

适用于Android和Java的类型安全的HTTP客户端

声明API

接口方法及参数的注解用于控制一个请求.

请求方法

每一个方法必须带有一个HTTP注解, 用于提供相应的请求方法和URL. 目前有5种内置的注解: GET , POST , PUT , DELETE和

@GET("users/list")

您还可以指定URL中的查询参数.

@GET("users/list?sort=desc")

操作URL

请求URL可以使用方法中的替换块和参数进行动态替换. 替换块是指由 { 和 } 包裹的字符串. 其对应的参数必须使用相同的字符串,并使用

@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);
对于复杂的查询参数组合, 可以使用
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String>
请求体
可以使用
@POST("users/new")
Call<User> createUser(@Body User user);

该对象同时也会被 Retrofit 实例所指定的转化器所转化. 如果没有添加转化器,则只有

编码表单和分段数据

方法也可以被声明为发送编码表单和分段数据.

当使用 @FormUrlEncoded 注解方法时, 则为发送编码表单数据.每个键值对使用

@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name")当使用 @Multipart 注解方法时, 则为分段请求.每段数据使用
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description")分段数据需要使用 Retrofit 中的某个转化器,或者通过实现
操作请求头
您可以使用
@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 提供相应的参数. 如果参数值为空, 则该请求头将会被忽略. 如果参数值不为空,则会调用该值的

@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)

对于所有请求都需要添加的请求头, 可以使用OkHttp interceptor来指定.

同步和异步

Call 实例既可以同步执行, 也可以异步执行. 每个实例只能被使用一次, 但通过调用

在Android中, 回调将会在主线程中执行. 在JVM中, 回调将发生在执行HTTP请求的线程中.

配置Retrofit

Retrofit 是一个将API接口转化为可调用对象的类. 默认情况下, Retrofit提供了默认的配置, 但他也允许进行自定义.

转化器

默认情况下, Retrofit只能将HTTP请求体反序列化为OkHttp的

并且在 @Body中只能接受

可以添加转化器以便支持其他类型. 为了您的使用便捷, 已经有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

以下是使用

Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHubService service = retrofit.create(GitHubService.class);

自定义转化器

如果您需要使用Retrofit不支持的内容格式(如YAML, txt, 自定义格式)与API进行通信, 或者您希望使用不同的库实现已有的格式, 您可以简单地创建自定义转化器.创建一个类继承

下载

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展示:


RETROFIT java 使用 retrofit操作符_User

直接看代码:

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;
    }
}