本例使用的是聚合数据的天气接口
http://apis.juhe.cn/simpleWeather/query
前提准备:
1.添加网络权限
<uses-permission android:name="android.permission.INTERNET"/>
2.导入需要的包 如果要结合rxjava 以下六个缺一不可
//导入retrofit
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
//OkHttp3
implementation 'com.squareup.okhttp3:okhttp:3.12.3'
//导入rxjava
implementation 'io.reactivex.rxjava2:rxjava:2.2.10'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
//Gson retrofit结合Gson框架作json数据转换
implementation 'com.squareup.retrofit2:converter-gson:2.6.0'
//RxJava2 Adapter retrofit结合rxjava使用的calladapter
implementation "com.squareup.retrofit2:adapter-rxjava2:2.6.0"
根据以下步骤一步步来:
1.根据服务器返回的json数据建立实体类
使用android studio的GsonFormat插件直接创建即可
2.创建网络请求api接口
public interface APIService {
//这里采用GET注解 关于其他注解的使用方式以后扩展
@GET("simpleWeather/query")
Call<WeatherBean> getWeather(@Query("city") String city, @Query("key") String key);
//我们需要在GET请求中加入两个参数city 城市 和key 请求的唯一识别码
}
3.创建retrofit实例 发送请求
public void getWeather() {
//创建retrofit实例 并传入baseurl和数据转换工厂(使用到了谷歌官方的Gson框架 用于将json数据转化为实体类)
Retrofit retrofit = new Retrofit
.Builder()
.baseUrl("http://apis.juhe.cn/")
.addConverterFactory(GsonConverterFactory.create())
.build();
//创建接口实例
APIService apiService = retrofit.create(APIService.class);
//对发送请求的url进行封装最终生成网络请求对象
Call<WeatherBean> call = apiService.getWeather("成都", "***这里是我的key*****");
//使用enqueue发送异步请求 并 回调对ui进行处理展示数据或者其他操作
//onResponse为请求成功后的操作
//onFailure为请求失败后的操作
call.enqueue(new Callback<WeatherBean>() {
@Override
public void onResponse(Call<WeatherBean> call, Response<WeatherBean> response) {
//response为服务器的返回数据 我们需要它 的body是我们转换后的实体类
//需要实体类中的什么内容根据需要自取
WeatherBean.ResultBean data = response.body().getResult();
//特别注意非空判断 很容易因为空指针问题导致崩溃
if(data!=null){textView.setText(data.getCity() + ":" + data.getRealtime().getInfo());}
else {textView.setText(response.body().getReason());}
}
@Override
public void onFailure(Call<WeatherBean> call, Throwable t) {
//如果发送错误请求错误显示出来
textView.setText(t.toString());
}
});
}
你可能会遇到的错误(也是我本人遇到的错 保持更新):
- 程序崩溃 data为null
此时说明请求成功了,执行了onResponse方法,但是服务器返回的数据中 你使用到的为null 比如我的例子中response.body().getResult()
这里获取的result对象 在我们向url请求不存在的城市时 就可能为null
所以一定要做好非空判断防止程序崩溃,再进一步分析数据为空的原因 - 请求出错,错误显示为:
java.net.UnknownServiceException: CLEARTEXT communication to *** not permit...
错误原因:
谷歌最新更新中不允许使用http非加密进行明文传输,只能使用https
解决办法:
https://www.jianshu.com/p/53eeb163b19a
以下是补充retrofit结合rxjava的使用
需要修改的地方:
api接口中 我们需要将返回类型修改为Observable<WeatherBean>
我这里新建了一个方法 getWeatherInRxjava
:
public interface APIService {
@GET("simpleWeather/query")
Call<WeatherBean> getWeather(@Query("city") String city, @Query("key") String key);
@GET("simpleWeather/query")
Observable<WeatherBean> getWeatherInRxjava(@Query("city") String city, @Query("key") String key);
}
实体类不做修改
然后再需要网络请求的地方:
//retrofit结合rxjava来使用
public void getWeatherInRxjava(){
//创建retrofit对象
Retrofit retrofit =new Retrofit
.Builder()
.baseUrl("http://apis.juhe.cn/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//引入rxjava适配
.build();
//这里较之以上是简写 其实除了加入rxjava 其他的也是一样的 只是没有把对象单独写出来
retrofit.create(APIService.class)//实例化网络请求接口
.getWeatherInRxjava("成都", "19fd22d1c21e46438c7e62f87087e2ef")//调用请求方法
.subscribeOn(Schedulers.io())//指定在io线程中发出请求
.observeOn(AndroidSchedulers.mainThread())//指定在主线程中处理请求结果
.subscribe(new Observer<WeatherBean>() {//声明观察者 来处理请求结果
@Override
public void onSubscribe(Disposable d) {//观察者成功订阅请求时
}
@Override
public void onNext(WeatherBean weatherBean) {//请求成功时
WeatherBean.ResultBean data = weatherBean.getResult();
if(data!=null){textView.setText(data.getCity() + ":" + data.getRealtime().getInfo());}
else {textView.setText(weatherBean.getReason());}
}
@Override
public void onError(Throwable e) {//请求出错时
textView.setText(e.toString());
}
@Override
public void onComplete() {//请求操作完成后
}
});
}
以上就是最简单的retrofit结合rxjava的使用
推荐阅读https://www.jianshu.com/p/464fa025229e
我们可以发现 这getWeatherInRxjava()
,getWeather()
两次请求中有很多共同点,比如创建retrofit对象的过程是完全一致的,其实我们对于相同的baseurl只需要创建一个retrofit就可以了,这里可以将网络请求中,相对比较重复的过程封装起来,以达到清晰代码结构和节省内存的目的,这个过程做到极致就是MVP框架了
网友评论