Retrofit简单使用

为什么要写这篇博客呢?

  • 由于主要从事系统应用的开发,很少涉及到网络相关的开发;
  • 最近要解决应用OTA问题,参考其他项目的代码,里面使用了Retrofit 库;
  • 平时看博客时,发现很多人都在使用Retrofit +RxJava+MVP/MVVM的模式进行开发网络应用。

正所谓天时地利人和,是时候学习下Retrofit 了。

Retrofit

A type-safe HTTP client for Android and Java.

学习一个库的使用方法,不是一开始学习它的原理,而是从最简单的API开始,一步步搭建自己的应用,当熟练到一定程度,或者现有的功能无法满足自己的需求时,才可进行深入的了解。

本文将根据Retrofit的官方文档,一步步介绍它在Android中的使用方法。

JSON数据

本文将利用Retrofit请求天气预报的Json数据为主线。天气预报Json数据的HTTP请求地址为:

1
http://www.weather.com.cn/data/sk/101110101.html

其中101110101为城市代码,虽然这个API可以请求到数据,但是结果却不是真实的天气状况-_-||。更多天气预报接口API的介绍参见中国天气网-天气预报接口api
如果网络可达,且接口有效,那么可以得到如下数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"weatherinfo": {
"city": "西安",
"cityid": "101110101",
"temp": "23.3",
"WD": "西南风",
"WS": "小于3级",
"SD": "52%",
"AP": "962.7hPa",
"njd": "暂无实况",
"WSE": "<3",
"time": "18:00",
"sm": "1.2",
"isRadar": "1",
"Radar": "JC_RADAR_AZ9290_JB"
}
}

那么根据Json数据定义一个Weather类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Weather {

public WeatherInfo weatherinfo;

public static class WeatherInfo {
public String city;
public String cityid;
public String temp;
public String WD;
public String WS;
public String SD;
public String AP;
public String njd;
public String WSE;
public String time;
public String sm;
public String isRadar;
public String Radar;
}
}

使用Retrofit库

添加依赖

首先需要在build.gradle(Module)文件中添加依赖:

1
2
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'

顾名思义,第一个是Retrofit库本身;第二个Retrofit封装的gson库。

WeatherService

WeatherService类用于封装各种HTTP请求,不过本文中只有一个:

1
2
3
4
public interface WeatherService {
@GET("data/sk/{cityId}.html")
Call<Weather> getCityWeather(@Path("cityId") String cityId);
}

其中

  • @GET表示HTTP的GET方法;
  • data/sk/{cityId}.htmlhttp://www.weather.com.cn/data/sk/101110101.html去除Base Url后剩余的部分;
  • cityId表示城市代码,通过方法的参数传入;
  • @Path可以理解为参数将插入url的路径中。

WeatherRepository

WeatherRepository类用于封装上一步WeatherService的创建过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class WeatherRepository {
private static final String BASE_URL = "http://www.weather.com.cn/";
private WeatherService mWeatherService;

private WeatherRepository() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
mWeatherService = retrofit.create(WeatherService.class);
}

private static class SingletonHolder {
private static final WeatherRepository INSTANCE = new WeatherRepository();
}

public static WeatherRepository getInstance() {
return SingletonHolder.INSTANCE;
}

public WeatherService getWeatherService() {
return mWeatherService;
}
}

其中最主要的是mWeatherService的创建过程(WeatherRepository的构造函数),一是传入Base Url,二是添加Json数据转换器。

数据请求

最后一步就是请求数据。现在只要在合适的地方调用如下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
WeatherRepository.getInstance()
.getWeatherService()
.getCityWeather("101110101")
.enqueue(new Callback<Weather>() {
@Override
public void onResponse(@NonNull Call<Weather> call, @NonNull Response<Weather> response) {
Log.d(TAG, new Gson().toJson(response.body()));
}

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

该方法为异步调用,所以可以放在UI线程中。如果请求成功可以看到类似下面的log输出:

1
2019-01-20 16:15:41.700 5889-5889/com.ihuntto.retrofitweather D/MainActivity: {"weatherinfo":{"AP":"962.7hPa","Radar":"JC_RADAR_AZ9290_JB","SD":"52%","WD":"西南风","WS":"小于3级","WSE":"\u003c3","city":"西安","cityid":"101110101","isRadar":"1","njd":"暂无实况","sm":"1.2","temp":"23.3","time":"18:00"}}

如果请求失败可以看到类似下面的log输出:

1
2
3
2019-01-20 16:30:50.204 6643-6643/com.ihuntto.retrofitweather W/System.err: java.net.UnknownHostException: Unable to resolve host "www.weather.com.cn": No address associated with hostname
2019-01-20 16:30:50.208 6643-6643/com.ihuntto.retrofitweather W/System.err: at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:141)
2019-01-20 16:30:50.209 6643-6643/com.ihuntto.retrofitweather W/System.err: at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:90)

完整的代码在GitHub项目:RetrofitWeather

总结与想法

本文对Retrofit的介绍并不是十分全面,只适用于初学阶段,许多地方并未深入介绍,如@POST方法、@Headers添加静态HTTP头、自定义OkHttp,网上有很多详细介绍的文章,如网络加载框架 - Retrofit。有时候写博客的目的,并不是为了传播知识,而是为了巩固自己使用过的知识,加深自己的理解。

参考文档

[1] Retrofit
[2] 中国天气网-天气预报接口api
[3] 网络加载框架 - Retrofit