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

时间:2022-03-04 23:09:08
概念:
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 type, Annotation[] annotations) {

                return new Converter<ResponseBody, String>() {

                    @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(TAG, str);

} 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> response, Retrofit retrofit) {

        Log.e(TAG, response.body());

        Log.e(TAG, Thread.currentThread().getName());

    }



    @Override

    public void onFailure(Throwable t) {

        Log.e(TAG, t.getMessage(), t);

        Log.e(TAG, Thread.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<ResponseBody, String> fromResponseBody(Type type, Annotation[] annotations) {

                return new Converter<ResponseBody, String>() {

                    @Override

                   
public String convert(ResponseBody value) throws IOException {

                        return value.string();

                    }

                };

            }



            @Override

           
public Converter<String, RequestBody> toRequestBody(Type type, Annotation[] annotations) {

                return new Converter<String, RequestBody>() {

                    @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。所以两个版本号一定要差别开,当然,在使用上并没有多大差别。