此文针对初学android开发,基础比较薄弱的同学。总结了自己在使用Retrofit2+Rxjava2框架发送请求的一些经验。
由于只是为了实现功能,所以在代码的封装以及优化上没有做什么改进。
首先,一个请求,对应的url地址我们把它分为三个部分。
以我自己申请的一个api接口为例,我申请了一个获取手机号归属地api,具体使用方法在https://www.jisuapi.com/api/shouji/可以查看,大家也可以使用这个网站的其他api
它的请求地址的示例是这样:
https://api.jisuapi.com/shouji/query?appkey=yourappkey&shouji=13456755448
我们可以发现大部分请求都是这种格式,下面来说一下各个部分的含义
第一部分: https://api.jisuapi.com/shouji/ 这部分是基础url
第二部分:query (即?之前的那部分)这是请求名称
第三部分:appkey=yourappkey&shouji=13456755448 这是请求参数以及其对应的值
appkey和shouji分别是两个请求参数,它们等号后面是对应的值,每个请求参数之间是以&间隔的
当然,第二部分的请求名称不一定是query,也可以是shouji/query ,这时候只需要把基础url写为 https://api.jisuapi.com/即可
知道了请求地址的含义之后,我们还需要知道该请求返回的数据格式
一般来说,请求返回的是json对象,基础的做法是把json里的数据通过JSONObject取出并给对应的bean赋值
但这个方法往往过于繁琐,因此我们需要用到retrofit框架中的converter-gson
下面结合我的demo说说具体的使用步骤
第一步:添加依赖包
//RxAndroid
implementation 'io.reactivex:rxandroid:1.1.0'
//retrofit依赖Gson
implementation 'com.squareup.retrofit2:converter-gson:2.0.0'
//retrofit依赖RxJava
implementation 'com.squareup.retrofit2:adapter-rxjava:2.0.0'
我总共用到了这三个包,先大概解释下每个包在我代码中的作用,后面会具体说明
rxandroid 用到了AndroidSchedulers类的.mainThread()方法,指定操作要在主线程进行
converter-gson 用于将返回的json对象自动转化为bean类
adapter-rxjava 使用rxjava的观察者模式回调数据
第二步:创建返回结果的javabean
新建一个LocationRes类,里面的内容用GsonFormat插件自动生成,这样对应返回的json格式不会出错
在https://www.jisuapi.com/api/shouji/中我们可以查看返回的json字符串示例,复制它
{
"status": 0,
"msg": "ok",
"result": {
"province": "浙江",
"city": "杭州",
"company": "中国移动",
"cardtype": "GSM"
}
}
在file-settings-plugin中下载安装GsonFormat插件,在创建的类中alt+insert选择GsonFormat,在粘贴板中粘贴以上内容
则会自动生成javabean,效果如下
package com.putt.phonedemo;
public class LocationRes {
/**
* status : 0
* msg : ok
* result : {"province":"浙江","city":"杭州","company":"中国移动","cardtype":"GSM"}
*/
private int status;
private String msg;
private ResultBean result;
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public ResultBean getResult() {
return result;
}
public void setResult(ResultBean result) {
this.result = result;
}
public static class ResultBean {
@Override
public String toString() {
return "province='" + province + '\'' +
", city='" + city + '\'' +
", company='" + company + '\'' +
", cardtype='" + cardtype + '\'';
}
/**
* province : 浙江
* city : 杭州
* company : 中国移动
* cardtype : GSM
*/
private String province;
private String city;
private String company;
private String cardtype;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getCardtype() {
return cardtype;
}
public void setCardtype(String cardtype) {
this.cardtype = cardtype;
}
}
}
第三步:创建请求接口
新建一个PhoneService的接口
public interface PhoneService {
@GET("shouji/query")
Observable<LocationRes> getLocation(@Query("appkey") String key, @Query("shouji") String shouji);
}
每个@get注解修饰一个请求的方法,可以有多个请求,括号内是请求名称
这里我的请求参数是shouji/query,注意不要多余地在前方加上/或者后方加上?,因为基础url必须以/结尾
这里我定义了一个getLocation方法
它的返回对象是Observable< LocationRes> ,Observable是rxjava中的被观察者,泛型传入LocationRes对象
方法的参数以@query注解修饰,有几个请求参数就有几个@query
第四步:创建一个retrofit工具类
新建RetrofitHelper类
public class RetrofitHelper {
private static final String REQUEST_PATH = "https://api.jisuapi.com/";
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(2, TimeUnit.MINUTES)
.writeTimeout(2, TimeUnit.MINUTES)
.readTimeout(2, TimeUnit.MINUTES)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(REQUEST_PATH)//基地址
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
PhoneService phoneService = retrofit.create(PhoneService.class);
public Observable<LocationRes> getData(String key, String shouji) {
return phoneService.getLocation(key, shouji);
}
}
实例化一个OkHttpClient,设置几个超时时间
实例化一个Retrofit,传入基础url和上面的OkHttpClient
addConverterFactory,添加解析工具,传入创建的converter-gson
包的GsonConverterFactory
addCallAdapterFactory,添加RxJava适配器,传入创建的adapter-rxjava
包的RxJavaCallAdapterFactory
实例化一个PhoneService并赋值
定义一个getData方法,返回PhoneService的getLocation方法
第五步:MainActivity中的调用
public class MainActivity extends AppCompatActivity {
private static final String KEY = "a19f7a97539e8abc";
Button button;
TextView textView;
EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
}
private void initData() {
button = findViewById(R.id.bt_query);
textView = findViewById(R.id.tv_consequence);
editText = findViewById(R.id.et_phone);
}
public void query(View v) {
//调用封装好的retrofit请求方法
RetrofitHelper retrofitHelper = new RetrofitHelper();
retrofitHelper.getData(KEY, editText.getText().toString())
.subscribeOn(Schedulers.io())//IO线程
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<LocationRes>() {
//执行onNext后执行
@Override
public void onCompleted() {
Toast.makeText(MainActivity.this, "onCompleted!", Toast.LENGTH_SHORT).show();
}
//请求失败
@Override
public void onError(Throwable e) {
e.printStackTrace();
}
//请求成功
@Override
public void onNext(LocationRes locationRes) {
textView.setText(locationRes.getResult().toString());
}
});
}
}
query方法为按钮的点击事件
先实例化一个RetrofitHelper,调用之前的getData方法获取Observable,参数分别为apikey和用户在文本框输入的手机号
observeOn:传入rxandroid
包下的AndroidSchedulers.mainThread()方法,因为要进行ui操作,必须在主线程,否则会有警告
subscribe:用于设置观察者与被观察者的订阅关系,传入的observer为new Subscriber< LocationRes>,它需要做出回应,因此重写
onCompleted onError onNext 这三个方法
失败时进入onError,e.printStackTrace()查看错误信息
成功时进入onNext,这里写逻辑事件,紧接着进入onCompleted,这里一般写提示信息
https://github.com/Puttanata/Android