Retrofit三步理解之一 ------------------ Retrofit的简单使用总结

来源:互联网 发布:记者李翔被杀真相 知乎 编辑:程序博客网 时间:2024/05/22 08:11
概念:
Retrofit一开始看起来使用比较麻烦是因为它和其他网络请求框架不同的是它是通过注解和interface来进行网络请求,并且需要对返回数据进行特殊处理才能使用。

1. 简单使用,请求返回String数据
1) 定义接口,在Retrofit2.0和Retrofit1.*是不用的,这里只说明Retrofit2.0的使用
public interface ApiService {
    @GET("/")
    Call<String> getData();
}
简单的看,这只是一个简单的interface。
解释:
注意getData()方法上的注解是一个@GET(String), 表示请求网络的是get方法,而其中的参数是baseUrl后面的数据,例如http://www.baidu.com/ + / =http://www.baidu.com/
而其返回值也是一个Call的泛型对象,其中String是我们最后需要的东西。
2) 构造Retrofit对象,构造Retrofit对象的目的是为了获取Retrofit为网络请求而实现上面我们自定义的interface对象。
final Retrofit retrofit = new Retrofit.Builder()
        .client(new OkHttpClient())
        .baseUrl("http://www.baidu.com/")
        .addConverterFactory(new Converter.Factory() {
            @Override
            public Converter<ResponseBody?> fromResponseBody(Type typeAnnotation[] annotations) {
                return new Converter<ResponseBodyString>() {
                    @Override
                    public String convert(ResponseBody value) throws IOException {
                        return value.string();
                    }
                };
            }
        })
        .build();

final ApiService service = retrofit.create(ApiService.class);

一步步解释上面的代码,从第一行开始,构造Retrofit对象是通过Retrofit.Builder来构造的,可以指定OkHttpClient为网络请求框架,baseUrl就是表示网络请求的baseUrl, 然后需要一个将网络请求返回的数据转换成我们需要的数据的对象,最后通过Response#body得到的就是该类型。
然后通过构造的Retrofit对象生成一个我们定义的网络请求接口。
这样前期的准备工作都做完了。
3) 网络请求,网络请求分为同步和异步请求。
同步:
最后我们可以通过Retrofit为我们生成的interface对象调用其中的方法就生成一个Call<T>对象,然后通过Call#execute就可以进行同步的网络请求,得到一个Response<T>对象,然后通过Response#body就可以得到我们最后需要的T对象。
try {
    retrofit.Response<String> response = call.execute();
    String str = response.body();
    Log.e(TAGstr);
catch (IOException e) {
    e.printStackTrace();
}

这样同步网络请求就完成了。Response<T>对象是包裹了网络请求返回的所有消息,可以对其进行处理。

异步:
一般的异步都是使用一个回调对象对其进行处理。在Retrofit中,通过调用Call#enqueue方法将一个Callback<T>对象传入其中,然后异步网络请求就开始了。然后在Response<T>#onResponse和onFailure方法中进行处理结果。
call.enqueue(new Callback<String>() {
    @Override
    public void onResponse(Response<String> responseRetrofit retrofit) {
        Log.e(TAGresponse.body());
        Log.e(TAGThread.currentThread().getName());
    }

    @Override
    public void onFailure(Throwable t) {
        Log.e(TAGt.getMessage()t);
        Log.e(TAGThread.currentThread().getName());
    }
});

经过测试,和OkHttpClient不同的是,这里的回调是在main线程中,故可以直接在其中进行UI操作。
这样简单的网络请求就操作完成了。

2. 参数的使用
在Retrofit中为url添加参数和动态改变url提供注解来更改,@Path, @Query, @Body
@Path 动态改变请求的url
在定义interface的时候动态改变url
@GET("/users/{username}")
Call<String> getUser(@Path("username") String username);

注意上面的@GET注解,其中可以看成需要一个username来动态构造url,而在getUser方法中我们就需要传递这个参数,通过@Path就可以指定其username,这样就可以将url进行动态的改变了。

@Query 添加参数
在定义interface的时候添加参数
@GET("/user")
Call<String> getUser(@Query("id")long userId);

注意@Query可以为url添加参数,其中id为key,传入的userId就为value,这样就添加了参数。

@Body
使用post提交数据的时候,将我们需要提交的对象转换成网络请求的方式。
@POST("/user/register")
Call<String> registerUser(@Body String user);

像上面,这样就定义了一个接口方法,调用该接口方法需要传递参数进去,这个时候就需要将参数转换成网络请求的样式。这个操作也是通过Converter对象来进行的。
final Retrofit retrofit = new Retrofit.Builder()
        .client(new OkHttpClient())
        .baseUrl("http://www.baidu.com/")
        .addConverterFactory(new Converter.Factory() {
            @Override
            public Converter<ResponseBodyString> fromResponseBody(Type typeAnnotation[] annotations) {
                return new Converter<ResponseBodyString>() {
                    @Override
                    public String convert(ResponseBody value) throws IOException {
                        return value.string();
                    }
                };
            }

            @Override
            public Converter<StringRequestBody> toRequestBody(Type typeAnnotation[] annotations) {
                return new Converter<StringRequestBody>() {
                    @Override
                    public RequestBody convert(String value) throws IOException {
                        return RequestBody.create(MediaType.parse("application/json;charset=utf-8")value);
                    }
                };
            }
        })
        .build();

修改了构造Retrofit对象代码,从其中可以看到,在addConverterFactory(Converter.Factory)方法中有两个方法,其中一个是fromResponseBody就是将网络请求的结果转换成我们需要的数据类型,而另外一个toRequestBody就是将我们传入的类型转换成网络请求的类型。
同时注意,这里的ResponseBody和RequestBody对象都是OkHttp中的类,使用方式参考OkHttp的使用即可。
而在调用Call#execute或Call#enqueue进行网络请求的时候相关的Response对象是Retrofit包中定义的类,通过Response#body得到的结果是在Converter泛型对象定义的类型。

3. Retrofit2.0 中baseUrl和完整url构建的关系(没有证实)
baseUrl是作为API的地址,我们也可能更改它的值。
而在定义接口的时候我们需要为其中的方法添加@GET或@POST来标记其请求的方式,同时完整url的其他部分。
假设 baseUrl = "http://api.douban.com/base/movie/"
通过一些网络文档描述,如果我们在@GET/@POST中添加参数为"/list"以"/"开头则表示完整的url为"http://api.douban.com/list",注意后面的/base/movie都没有了,而如果在@GET/@POST中添加参数为"list"没有以"/"开头则表示完整的url为“http://api.douban.com/base/movie/list。
同时,如果在@GET/@POST中的参数本身就是一个完整的url,那么就会抛弃baseUrl而使用其参数上的url。

4. 混淆
-dontwarn retrofit.**
-keep class retrofit.** { *; }
-keepattributes Signature
-keepattributes Exceptions

5. 文件上传
通过给interface中的方法添加@Multipart,然后在方法中的参数添加@Part,参数类型为RequestBody,这样就可以将文件由RequestBody包裹,然后再通过Retrofit进行处理即可。RequestBody是OkHttp的API。
关于文件上传,曾经遇到的一个问题:支持多文件上传的情况下,有可能不上传文件,那么这个问题怎么解决呢。File file = null; 第三方jar包不支持怎么办。
关于多文件上传,因为Retrofit底层使用的是OkHttp,故应该关注RequestBody携带多个文件的情况。
Get OkHttp 2.1, and use MultipartBuilder.addFormDataPart() which takes the filename as a parameter.

其他操作参考其他Retrofit文档和官方文档:http://square.github.io/retrofit/

注:
在写这篇总结的时候,Retrofit的版本仍然是2.0.0-Beta1, 现在的版本是2.0.0-Beta3, 虽然看版本号变化不大,但是两者的包名已完全不一样,2.0.0-Beta3使用的也是okhttp3,所以两个版本一定要区别开,当然,在使用上并没有多大区别。
1 0
原创粉丝点击