Retrofit2.0(一)retrofit基本使用讲解和Converter转换器使用

Retrofit2.0使用


应用程序通过 Retrofit 请求网络,实际上是使用 Retrofit 接口层封装请求参数、Header、Url 等信息,之后由 OkHttp 完成后续的请求操作,在服务端返回数据之后,OkHttp 将原始的结果交给 Retrofit,后者根据用户的需求对结果进行解析的过程


根据需要添加依赖

//retrofit2
compile 'com.squareup.retrofit2:retrofit:2.1.0'
//okhttp
compile 'com.squareup.okhttp3:okhttp:3.9.0'
//Gson converter
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
//RxJava2 Adapter
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
//rxandroid2
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
// Log信息拦截器
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'

在AndroidManifest.xml中添加权限

<!-- 允许程序打开网络套接字 -->
<uses-permission android:name="android.permission.INTERNET" />

开始!


一、 定义接口

1.1 GET方式

// 没有参数的GET请求
public interface HttpService {
@GET(".")
Call<ResponseBody> getPermission();
}

说明:GET()中的" “填写与下方的baseUrl拼接的path构成完整的URL地址
若没有内容,则填写“.” 或者”/" (但是我测试的时候只有填写 “.” 才正确)
填写"/"提示 NullPointException
< ResponseBody >为默认的请求主体,是OKHttp3的,可以修改为自定义的Bean类型,后面再详细讲

并且不是只能一个网络请求一个接口


1.2
当然 GET中也可以带有内容 如带有路径

@GET("路径名") //baseUrl与路径名构成完整路径
Call<ResponseBody> getPermission();

1.3
带有变量

@GET("路径名/{变量名}") //baseUrl与路径名构成完整路径
Call<ResponseBody> getPermission(@Path("变量名") 变量类型 形参名);

**1.4.1 **
键值对形式
@Query

@GET //当有URL注解时,这里的URL就可以省略了
Call<ResponseBody> getPermission(@Url String url, @Query("key") String values);

1.4.2
键值对形式
@QueryMap

@GET("路径名")
Call<ResponseBody> getPermission(@QueryMap Map<String, Object> map);

2.1 POST方式
@Field

// 要加上这个  表示请求体是一个表单
@FormUrlEncoded
// POST方式 如果带参数与baseUrl构成地址
 @POST("access_token?")
       //通过@Field来指定key,后面跟上value
        Call<ResponseBody> getAccessToken(
          @Field("client_id") String client_id,@Field("client_secret") String client_secret,
          @Field("grant_type") String grant_type,@Field("redirect_uri") String redirect_uri,
          @Field("code") String code
          );

一定要写至少一个的@Field 否则会报错 Form-encoded method must contain at least one @Field.
field与field之间是原网址的&
并且自动加上key=value的=


**2.2 **
@FieldMap 形式

 // 要加上这个  表示请求体是一个表单
    @FormUrlEncoded
    @POST("xxx")
    Call<ResponseBody> getRegister(
            @FieldMap Map<String, Object> map
    );

同一个请求方式 同一个网址 ,不同参数值
用 @Field 传入不同参数即可 或者 @FieldMap
同一个请求方式 同一个网址 ,不同参数个数
用@FieldMap


3 上传文件(图片)
通过@part和@partMap方式
要与@Multipart一起用
如:上传一张图片加key,value键值对

3.1 定义接口
这里的key values 的值要为 RequestBody形式的 String形式的不可

 @Multipart
    @POST("XXX")
    Observable<XXBean> upLoadPic(
            @PartMap Map<String,RequestBody> map,
            @Part MultipartBody.Part file
    );

3.2 设置键值对的值为 RequestBody形式

// 设置传输格式为纯文本传输
  MediaType textType = MediaType.parse("text/plain");
  // 将值设置为 RequestBody形式的
  RequestBody formNo = RequestBody.create(textType, "490");
  RequestBody moduleNo = RequestBody.create(textType, "944");
  // 加入Map中
  Map<String, RequestBody> upLoadArgsMap = new HashMap<>();
  upLoadArgsMap.put("formNo",formNo);
  upLoadArgsMap.put("moduleNo",moduleNo);
 

3.3 将文件转换为RequestBody形式

RequestBody requestBodyFile =
RequestBody.create(MediaType.parse("multipart/form-data"), compressedFile);

3.4 创建 MultiFormBody

MultipartBody.Part multipartBodyFile = 
MultipartBody.Part.createFormData("image", 
compressedFile.getName(), requestBodyFile);
// 这里的 image 为 服务器的请求参数key

二 创建Retrofit实例
创建一个RetrofitUtil类

//创建Retrofit实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://45.32.72.80/test/lastTime/")  // 基础的url地址 并且结尾一定要以/结尾!
.client(okhttpBuilder.build())
.build();

结尾要以/结尾,否则会抛出java.lang.IllegalArgumentException: baseUrl must end in /:异常
若你的网址不能以/结尾,那可以截取网址中有/的部分 然后剩下的放在GET("")中就可以了


三 用Retrofit创建一个HttpService的代理对象

 //用retrofit创建HttpService对象
        HttpService httpService = retrofit.create(HttpService.class);

四 接口调用

Call<ResponseBody> call = service.getPermission(); 

五 异步请求

// 用法和OkHttp的call如出一辙,
// 不同的是如果是Android系统回调的OnResponse和OnFailure执行在主线程
call.enqueue(new Callback<ResponseBody>() {
        @Override
        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
            try {
            String str=response.body().string();
               Log.i("onresponse",str);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(Call<ResponseBody> call, Throwable t) {
            Log.i("onfailure","onfailure");
            t.printStackTrace();
        }
    });

至此,一个简单的网络请求就做好了!


请求重试:

mCall.clone().enqueue()

因为是retry 若是再 call.excute或者 call.enqueue(其实内部也是会excute)
则会出错 因此 可以通过 clone出多一个实例出来(代价很低)再去做enqueue


请求取消

call.cancle()

可以立刻结束当前的请求


retrofit注解:
请求方法:

这里写图片描述

①HTTP注解则可以代替以上方法中的任意一个注解
有3个属性:method、path、hasBody

method 表示请求的方法,区分大小写
path表示路径
hasBody表示是否有请求体


标记类
这里写图片描述


参数类

这里写图片描述


支持{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型
除了{@link okhttp3.MultipartBody.Part} 其他都要加上 表单字段
即 如:
multipart/form-data (上传文件,是上传二进制数据)
application/x-www-form-urlencoded(默认)
application/json
text/xml
text/html (传递html代码的编码类型,在发送头文件时才用得上)
text/plain 是纯文本传输


call< >这个里面的是得到的返回的类型,默认为OKhttp的ResponseBody类型,可以通过 respone.body.string() 获取String类型的 json数据,再解析
当然你也可以使用Call< Bean > get() 形式,自定义为自己的javaBean类 再通过GSON解析。需要给Retrofit添加Gson转换器 (见下方的 Converter

call<> 方法(@Body )这个Body则是自己的类,可以通过该类传递数值给方法,如上传 JSON数据


Converter
默认情况下Retrofit只支持将HTTP的响应体转换换为ResponseBody,
而Converter是Retrofit为我们提供用于将ResponseBody转换为我们想要的类型

通过GsonConverterFactory为Retrofit添加Gson支持
1 添加gson库

compile 'com.squareup.retrofit2:converter-gson:2.0.2'

2 配置GSON (非必要)

Gson gson = new GsonBuilder()
      .setDateFormat("yyyy-MM-dd hh:mm:ss")
      .create(); 

3 创建retrofit并添加对应的Converter

Retrofit retrofit = new Retrofit.Builder()
      .baseUrl("http://localhost:4567/")
      //可以接收自定义的Gson,当然也可以不传
      .addConverterFactory(GsonConverterFactory.create(gson))  // 不配置gson则括号可以为空 
      .build();

4 修改接口

public interface APIService{
        @POST("XXX")
        Call<LoginBean> getLoginData();
    }

5 创建APIService的代理对象


APIService service = retrofit.create(APIService.class);


6 接口调用

Call<LoginBean> call = service.getLoginData();

7 call内部具体实现

call.enqueue(new Callback<LoginBean>() {
            @Override
            public void onResponse(Call<LoginBean> call, Response<LoginBean> response) {
                // 在参数中已经将其转换为想要的类型了
                 String result = response.getXXX();
                System.out.println(result);
            }

            @Override
            public void onFailure(Call<LoginBean> call, Throwable t) {
                t.printStackTrace();
            }
        });

若通过 < Bean >方式,但是又想获取回传的完整JSON数据,则可以通过增加拦截器的方式,参考:
http://blog.csdn.net/weixin_37577039/article/details/79495797


retrofit (okhttp)的onresponse(1-5开头的返回码都会走onResponse) 说明已经走出去了

并且若返回404 返回502 则返回的 response.body是空的 去.toString会导致空指针错误
因此要加 not null 判断

可以在onResponse 或者 onFailure 中 的call 获取到 call.request() 然后去获取 url等相关请求的信息

可以根据不同返回码 response.code() 去进行不同的操作

onError (超时 网络无连接 网络状态差时) 根本走不出去

拦截器并不是 初始化 retrofit的时候就 添加进去 而是 调用方法时(intercept) 才动态的去添加
但是 和其他的一样 创建 okhttpclient时 只调用一次 .addInterceptor()


Retrofit流程与设计模式
在这里插入图片描述


Retrofit的坑

1 注解的参数没用对
@Body和@Multipart或者@FormUrlEncoded不能同时使用
通过找出Exception的类型和内容,去源码中发现有一个地方写了当(isFromEncoded或者isMultipart)则抛出异常


Rxjava
上文的Converter是对于Call< T >中T的转换,而CallAdapter则可以对Call进行转换,这样的话Call< T > 中的Call也是可以被替换的,而返回值的类型就决定你后续的处理程序逻辑,同样Retrofit提供了多个CallAdapter,这里以RxJava的为例,用Observable代替Call

**Rxjava2学习:**http://blog.csdn.net/weixin_37577039/article/details/78555208


Retrofit2+Rxjava2学习参考下一篇:
http://blog.csdn.net/weixin_37577039/article/details/79495443


Rxjava2+retrofit2+OKHttp3+GSON实践:
http://blog.csdn.net/weixin_37577039/article/details/78556296


参考链接:
http://www.jianshu.com/p/308f3c54abdd

http://square.github.io/retrofit/ 官方教程

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值