Retrofit2.0的使用总结
工作中的网络访问框架使用的就是retrofit2.0,用了一段时间感觉还不错,分享一下使用retrofit框架的基本使用方法和经验.
添加依赖:
compile ‘com.squareup.retrofit2:retrofit:2.0.2’
1. 构建Retroift对象
首先使用retrofit需要一个Retrofit对象,需要设定baseUrl即根地址,同时关联网络访问,使用的就是okhttp网络访问。也要规定解析的方式,使用Gson来解析,一般还要配合Rxjava使用,所以需要定义一些基本的转换方式。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.baidu.com")
.client(okHttpClient) .addConverterFactory(CustomGsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
这是典型的build模式,addConvertFactory是为了表明返回值的解析方式,这里使用的是Gson解析,addCallAdapterFactory是表明支持RxJava的形式。 okHttpClient表明了一个okhttp的对象。可以制定网络访问的一系列参数,比如网络超时,拦截器,打印日志等等功能。
//okhttp的日志拦截器
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//okhttp的参数拦截器
RequestParamInterceptor requestParamInterceptor = new RequestParamInterceptor();
//构建okhttp的对象
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.addNetworkInterceptor(requestParamInterceptor)
.build();
2. 构建接口来传递参数
GET方式提交
public interface ApiHomeService {
@GET("/GetCategory")
Observable<CategoryEntity> getCategoryList();
}
//获取ApiHomeService对象
ApiHomeService service = retrofit.create(ApiHomeService.class);
通过这种方式可以获得接口对象,通过service.getCategoryList ()来获得一个Observable对象,关于Observable对象就是Rxjava的一个可观察对象,要了解Rxjava的相关可以参考: 给 Android 开发者的 RxJava 详解。Observable中的泛型就为接口返回的Json对应的实体类。然后可以通过Rxjava方法处理返回结果:
Observable<CategoryEntity> observable = service.geetCategoryList();
//网络请求在io线程
observable.subscribeOn(Schedulers.io()
//回调在主线程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscribe<CategoryEntity>){
@Override
public void onCompleted() {
//结束时调用
}
@Override
public void onError(Throwable e) {
//处理出现错误
}
@Override
public void onNext(CategoryEntity enty){
//解析完成的实体类
}
这就是网络访问的全过程,当然这个只是基本的Get请求,如果想要加入参数,需要这样做:
//在ApiHomeService中
@GET("start-image/{res}")
Observable<WelcomeBean> getWelcomeInfo(@Path("res") String res);
这是在链接中加入参数,{res}相当于占位,处理的链接类似于 www.baidu.com/aaa中的aaa作为参数。还有:
//在ApiHomeService中
@GET("start-image")
Observable<WelcomeBean> getWelcomeInfo(@Query("res") String res);
这种参数相当于键值对传递,拼接到链接后,类似于 www.baidu.com?res = “5”。
有Get肯定少不了Post。 其实只要把GET注解改为POST也是可以的。
介绍一下POST的方式
post提交可以提交json格式的字符串,如何实现呢?
@POST("delUser")
Call<List<User>> delUser(@Body User user);
service.delUser(new User("1","张三","23"))
就这么简单,用Body来标注对象即可传递。当然 POST方式还可以以表单方式提交
@FormUrlEncoded
@POST("getCity")
Observable<CityEntity> getCountryCity(@Field("CountryName") String countryName
);
这里不要忘了添加FormUrlEncoded,表示表单提交,同时用@Field来标注表明表单提交的键值对。
关于上传图片视频
图片视频的上传也是App的必不可少的一部分,有几种方式可以传递单文件和多文件:
@Multipart
@POST("upload")
Observable<BaseEntity> uploadFile(
@Part MultipartBody.Part photo,
@Part("filename") RequestBody name);
@MultiPart的意思就是可以传递多个@Part,我们这里使用了2个@Part,第一个我们准备上传个文件,使用了MultipartBody.Part类型,另一个为文件名。
MultipartBody和 RequestBody又是什么呢?
//上传的文件
File file = new File(Environment.getExternalStorageDirectory(), "upload.png");
//生成MultipartBody.Part对象
RequestBody photoRequestBody = RequestBody.create(MediaType.parse("image/png"), file);
//这里也可以使用MediaType.parse("video/*")传视频或者MultipartBody.FORM的形式
MultipartBody.Part photo = MultipartBody.Part.createFormData("photos", "icon.png", photoRequestBody);
//调用
Observer<BaseEntity> observer = service.uploadFile(photo, RequestBody.create(null, "aaaa"));
还有一种方式就是传递RequestBody,看一下如何实现:
@Multipart
@POST("upload")
Observable<BaseEntity> uploadFile(
@Part("file\"; filename=\"splash.png") RequestBody photo,
@Part("filename") RequestBody name);
看到这个直接懵逼了,参数什么鬼。 其实也就是拼接了一下传递的值,file当作传递的参数,filename是需要传递的文件名,当然也可以自定义或者加个时间戳防止重复:
@Part("file";filename=\"VideoFS"+new Date().getTime()+file.getName + " ")
用这种方式可以拼接时间戳,同时如果想要同时传递多个文件可以这样:
@Multipart
@POST("upload")
Observable<BaseEntity> upload(
@PartMap Map<String, RequestBody> params);
通过PartMap来标注,这时候需要传递的是一个Map集合,把想要传递的参数或文件塞到集合中,一次性传递多个文件:
File file = new File(Environment.getExternalStorageDirectory(), "video.mp4");
Map<String,RequestBody> maps= new HashMap<>();
RequestBody video = RequestBody.create(MediaType.parse("video/*"),file)
Map<String,RequestBody> photos = new HashMap<>();
maps.put("video\"; filename=\"video.mp4", video);
maps.put("filename", RequestBody.create(null, "aaaaa"));
Observable<BaseEntity> observable = service.upload(maps);
这样就可以上传多文件了,有多少塞多少。。。