Retrofit网络框架入门使用

yellowdog 发布于1年前 阅读12191次
0 条评论

 

1.简介

retrofit其实就是对okhttp做了进一步一层封装优化。我们只需要通过简单的配置就能使用retrofit来进行网络请求了。

Retrofit能够直接返回Bean对象,例如如果我们进行一个网络接口的请求,返回来一串json字符串。那么这个时候一般我们都要拿到这个json字符串后进行解析得到对应的Bean对象,Retrofit只要依赖一下Gson的转换库然后进行简单的配置就能够直接拿到Bean对象了,不需要我们自己去解析。

接触过OKHttp的人会发现,Retrofit和OKHttp的代码有些地方有很大的相似度。

他的性能非常的棒,国外大牛(被墙了)已经做过测如下图:

这里写图片描述

看了这个图之后你有什么想法?

Talk is cheap, show me the code!!

2.快速使用

在实际项目开发中get、post请求使用居多。那我们以get请求来做个入门小案例。

http://ip.taobao.com/service/getIpInfo.php?ip=8.8.8.8

以上连接是一个get请求方式,参数在地址后面使用“?”进行名值对的拼接。请求的结果是一个json字符串数据,如下

{"code":0,"data":{"country":"\u7f8e\u56fd","country_id":"US","area":"","area_id":"","region":"","region_id":"","city":"","city_id":"","county":"","county_id":"","isp":"","isp_id":"","ip":"8.8.8.8"}}

来个简单的Demo界面如下:
功能非常简单,一个输入框输入IP地址,然后获取IP地址所在的国家。
这里写图片描述

1)环境的配置

现在估计很少人用eclipse做项目开发了,eclipse的方式就不另赘述了(GitHub上也是有jar依赖下载的)。我们这里的开发工具是用的Android Studio,在 GitHub项目地址:https://github.com/square/retrofit可以找到Gradle的依赖代码:
添加两个依赖:retrofit依赖,和gson转换器。

compile 'com.squareup.retrofit2:retrofit:2.1.0'//目前最新的版本compile 'com.squareup.retrofit2:converter-gson:2.1.0'//添加好这个依赖后我们就可以进行数据转换器的配置了,retrofit内部就会帮我们去转换json字符串为Java对象

在AS里面的效果如下:
这里写图片描述

converter-gson依赖的版本号与retrofit依赖版本号保持一致,我们在GitHub上可以看到,他们在同一个工程里面的。

2)代码

布局非常简单就不另贴代码了,类也不多参看下面的包结构图
这里写图片描述

Retrofit操作步骤

① 先把接口返回来的数据bean对象写好。

可以直接使用工具转化,如GsonFormat工具

public class IpInfo {public int code;public DataBean data;public static class DataBean {public String country;public String country_id;public String area;public String area_id;public String region;public String region_id;public String city;public String city_id;public String county;public String county_id;public String isp;public String isp_id;public String ip;

    }

}
② 定义API接口

一般来讲都是处理遵循RESTful接口规范的http接口,我们需要把接口转化为Java Interface。

/** * 这个接口就是普通的借口类,但是看到里面的方法来,会有一些注解定义相关的功能 * 如@GET定义请求方式为get请求方式,如果有参数可以使用@Query、@QueryMap定义 */public interface IpService {/** * @return 固定返回值为Call,其中泛型指定是进行请求后返回最终得数据类型。 */@GET("getIpInfo.php")   //@GET 定义网络请求方式Call<IpInfo> getIpInfo(@Query("ip") String ip); //@Query("ip") 指的是传入的参数名为ip,值为调用方法传入的值形参ip}
③ 初始化Retrofit,创建接口实例,进行异步请求

代码注释灰常细致了

/** *Retrofit简单实用案例 * * 采用http://ip.taobao.com/service/getIpInfo.php?ip=202.178.10.2 地址进行查询 */public class MainActivity extends AppCompatActivity {public static final String baseUrl = "http://ip.taobao.com/service/";private TextView tvResult;private EditText etIp;

    IpService ipService;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvResult = (TextView) findViewById(R.id.tv_result);
        etIp = (EditText) findViewById(R.id.et_ip);

        initRetrofit();
    }     /** * 初始化Retrofit实例,并创建接口类。 * 注意:IpService不需要我们去实现,直接Retrofit=类有create方法生成。 */private void initRetrofit() {//创建Retrofit的实例,把Gson转换器设置下Retrofit retrofit = new Retrofit
                .Builder()
                .baseUrl(baseUrl)//设置API的基础地址.addConverterFactory(GsonConverterFactory.create())//设置后才才支持json字符串转化为Bean.build();//使用Retrofit的create方法传入创建接口实例ipService = retrofit.create(IpService.class);
    }/** * 布局中查询按钮配置的点击事件 * @param view */public void check(View view) {

        String ip = etIp.getText().toString();if (TextUtils.isEmpty(ip)) {
            Toast.makeText(this, "ip 不能为空", Toast.LENGTH_SHORT).show();return;
        }//调用接口声明的方法Call<IpInfo> ipInfoCall = ipService.getIpInfo(ip);//call可以直接调用异步方法,进行结果获取。需要传入接口回调Callback,ipInfoCall.enqueue(new Callback<IpInfo>() {@Overridepublic void onResponse(Call<IpInfo> call, Response<IpInfo> response) {//判断网络请求是否成功,网络请求返回code为[200..300)那么与后台连接成功。否则连接失败if (response.isSuccessful()) {//直接拿到JavaBeanIpInfo ipInfo = response.body();//这里直接可以进行UI操作,OKHttp是不行的哦tvResult.setText(ipInfo.getData().getCountry());

                } else {//请求失败。如果代码执行到这里来说明是有跟后台握手的,是后台处理有问题,如404(没有资源),500(后台报错了)tvResult.setText("查询失败!! -->code="+response.code());
                }
            }@Overridepublic void onFailure(Call<IpInfo> call, Throwable t) {//请求失败。如,没有声明网络权限、没有网络、或者是Retrofit 异常内部处理异常(如Gson解析失败)也是会到这里t.printStackTrace();
                tvResult.setText("查询失败:"+t.getCause());
            }
        });

    }
}

3.常用注解

GET:get 请求方式
POST:post请求方式
Query:定义get请求参数
QueryMap:定义get请求参数
Field:定义post请求参数
FieldMap:定义post请求参数
Header:定义头参数
HeaderMap:定义头参数
Headers:定义头参数
Path:动态路径
来看看代码是怎么实现的:

public interface SampleApi {//----------------------GET 请求方式 start --------------------------------/** * 注解:GET,QUERY,QUERYMAP 的使用 *//** * get 请求固定参数形式 * * @return */@GET("demo?username=zhanghsan&password=123455")
    Call<SampleResponse> getFun();/** * 使用@Query注解进行参数传递 * * @param username * @param password * @return */@GET("demo")
    Call<SampleResponse> getFun(@Query("username") String username, @Query("password") String password);/** * 使用@QueryMap注解 Map集合进行参数传递 * * @param params * @return */@GET("demo")
    Call<SampleResponse> getFun(@QueryMap Map<String, Object> params);//----------------------GET 请求方式 end --------------------------------//----------------------POST 请求方式 start --------------------------------/** * POST,Field,FieldMap,FormUrlEncoded(POST 方式请求有参数的时候一定不要忘记了这个注解) *//** * post使用@Query注解进行参数传递 * * @param username * @param password * @return */@FormUrlEncoded@POST("demo")
    Call<SampleResponse> postFun(@Field("username") String username, @Field("password") String password);/** * POST使用@FiledMap Map集合进行参数传递 * * @param params * @return */@FormUrlEncoded@POST("demo")
    Call<SampleResponse> postFun(@FieldMap Map<String, Object> params);//----------------------POST 请求方式 end --------------------------------//----------------------head参数添加start --------------------------------/** * Headers,Header,HeaderMap * *//** * 有些接口需要传送一些操作客户端系统的信息,比如系统类型,系统版本等如下 * * @param username * @param password * @return */@Headers(
            {"os:Android", "osversion:5.0"})@FormUrlEncoded@POST("demo")
    Call<SampleResponse> postFunWithHead(@Field("username") String username, @Field("password") String password);/** * 有些接口需要传送一些操作客户端系统的信息,比如系统类型,系统版本等如下 * * @param username * @param password * @return */@FormUrlEncoded@POST("demo")
    Call<SampleResponse> postFunWithHead(@Header("os") String os, @Header("osversion") String osversion, @Field("username") String username, @Field("password") String password);/** * 有些接口需要传送一些操作客户端系统的信息,比如系统类型,系统版本等如下 * * @param headParams head 参数,键值对的形式存储到map集合中去 * @param username * @param password * @return */@FormUrlEncoded@POST("demo")
    Call<SampleResponse> postFunWithHead(@HeaderMap Map<String, String> headParams, @Field("username") String username, @Field("password") String password);//----------------------head参数添加end --------------------------------//----------------------path 注解 --------------------------------/** * Path注解使用时在请求方式注解后面的URL设置一个占位符,使用大括号包裹。在方法形参类型前使用@Path("占位符")。 */@FormUrlEncoded@POST("{path}")
    Call<SampleResponse> postFunWithHead(@Path("path") String path, @HeaderMap Map<String, String> headParams, @Field("username") String username, @Field("password") String password);
}

Activity代码

public class SampleActivity extends AppCompatActivity {EditText etName;
    EditText etPassword;
    TextView tvResult;
    SampleApi sampleApi;
    SampleCallBack callback;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample);

        etName = (EditText) findViewById(R.id.et_name);
        etPassword = (EditText) findViewById(R.id.et_password);
        tvResult = (TextView) findViewById(R.id.tv_result);//使用链式调用建立sampleApi = new Retrofit
                .Builder()
                .baseUrl("http://10.0.2.2:8080/")
                .addConverterFactory(GsonConverterFactory.create())
                .build()
                .create(SampleApi.class);

        callback = new SampleCallBack();


    }/** * 按钮点击事件 * * @param view */public void submit(View view) {
        tvResult.setText("正在请求....");

        String name = etName.getText().toString();
        String password = etPassword.getText().toString();if (TextUtils.isEmpty(name) || TextUtils.isEmpty(password)) {
            Toast.makeText(this, "参数不能为空", Toast.LENGTH_SHORT).show();return;
        }
        Call<SampleResponse> call;
        switch (view.getId()) {case R.id.btn_get:
                call = sampleApi.getFun(name, password);
                call.enqueue(callback);break;case R.id.btn_post:
                call = sampleApi.postFun(name, password);
                call.enqueue(callback);break;case R.id.btn_head:// call = sampleApi.postFunWithHead(name, password);//第一种,直接静态定义方式,看接口方法// call = sampleApi.postFunWithHead("ios","10.10.10",name, password);//第二种,可以动态配置值得方式Map<String, String> map = new HashMap<>();
                map.put("os", "android");
                map.put("osversion", "9.9.9999999");// call = sampleApi.postFunWithHead(map, name, password);//第三种,可以动态配置参数和值得形式call = sampleApi.postFunWithHead("demo",map, name, password);//第四种,结合Path定义路径call.enqueue(callback);break;
        }
    }/** * @param result * 显示结果 */public void showResult(String result) {
        tvResult.setText(result);
    }/** * 回调实现类 */public class SampleCallBack implements Callback<SampleResponse> {@Overridepublic void onResponse(Call<SampleResponse> call, Response<SampleResponse> response) {//判断网络请求是否成功,网络请求返回code为[200..300)那么与后台连接成功。否则连接失败if (response.isSuccessful()) {//直接拿到JavaBeanSampleResponse sampleResponse = response.body();//这里直接可以进行UI操作,OKHttp是不行的哦showResult(sampleResponse.toString());

            } else {//请求失败。如果代码执行到这里来说明是有跟后台握手的,是后台处理有问题,如404(没有资源),500(后台报错了)showResult("查询失败!! -->code=" + response.code());
            }
        }@Overridepublic void onFailure(Call<SampleResponse> call, Throwable t) {//请求失败。如,没有声明网络权限、没有网络、或者是Retrofit 异常内部处理异常(如Gson解析失败)也是会到这里t.printStackTrace();
            showResult("查询失败:" + t.getCause());
        }
    }

}

运行效果

这里写图片描述

4.URL操作注意事项

拼接注意,建议baseUrl用“/”结尾,接口中请求方式后面的url不用”/”开头

例子:baseUrl=http://10.0.2.2:8080/market/ url=home

错误案例

案例一:
baseUrl=http://10.0.2.2:8080/market url=home
—>http://10.0.2.2:8080/home
分析:默认用最后一个斜线去拼接

案例二:
baseUrl=http://10.0.2.2:8080/market url=/home
—>http://10.0.2.2:8080/home
分析:url中开始的斜线代表主机地址http://10.0.2.2:8080

源代码下载

Retrofit还能够实现上传下载以及 结合RxJava使用,等下回分解!


 
需要 登录 后回复方可回复, 如果你还没有账号你可以 注册 一个帐号。