简单应用实例: 在介绍如何使用Retrofit之前先做点准备。首先要有个开放的API供我们使用网络去获取信息,接下来的例子将使用OpenWeather来练习下,如下是openWeather的地址:http://openweathermap.org/ 和众多的API一样都需要申请一个开发者的key,申请key的过程就不在这里介绍了。
在AS中引入RxJava + Retrofix
apply plugin: 'com.android.application' android { compileSdkVersion 23 buildToolsVersion "23.0.3" defaultConfig { applicationId "com.idealist.doumusic" minSdkVersion 15 targetSdkVersion 23 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt' ), 'proguard-rules.pro' } } } dependencies { compile fileTree (dir: 'libs' , include : ['*.jar' ]) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.3.0' compile 'com.android.support:design:23.3.0' compile 'io.reactivex:rxjava:1.1.0' compile 'io.reactivex:rxandroid:1.1.0' compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4' compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4' compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4' compile 'com.google.code.gson:gson:2.6.2' }
开始我们先创建一个接口,关键部分先留空,后面我带大家一点一点往上面填:
public interface IDouMusic { @GET("" ) Callback<WheatherResult> getWheatherResult () ; }
首先到这一步大家一定都申请了对应的APPID,也就是对应的APIkey,类似f8d8ead8299f963abcded5c40c0bcb81 找不到申请地方的我这里贴个地址:http://openweathermap.org/appid 申请到APPID后怎么使用呢?整个模板是这样的,只要在最后的申请后面添加APIKEY即可http://api.openweathermap.org/data/2.5/forecast/city?id=524901&APPID={APIKEY} 前面的又是什么呢?大家进入这个页面http://openweathermap.org/api 这里面有很多的查询方案,作为例子我们选个简单的,当前的天气情况:http://openweathermap.org/current 这里提供了很多的查询方式,可以按照城市名,城市id等信息查询。 你不知道城市id怎么表示?可以到这个地方下载city.list.json 查询 http://bulk.openweathermap.org/sample/ 比如我们以广东惠州为例,查询当天天气,那么访问的地址应该是:http://api.openweathermap.org/data/2.5/weather?q=Huizhou&APPID=f8d8ead8299f963abcded5c40c0bcb81 注意这里的APIKey需要换成大家自己申请的。将上述的地址拷贝到浏览器上这时候就会返回下面信息:
{ "coord": { "lon": 114.4 , "lat" : 23.08 }, "weather": [ { "id": 802 , "main" : "Clouds" , "description" : "scattered clouds" , "icon" : "03n" } ], "base": "stations" , "main" : { "temp": 300.93 , "pressure" : 995 , "humidity" : 49 , "temp_min" : 300.93 , "temp_max" : 300.93 }, "wind": { "speed": 1.03 , "gust" : 7.71 }, "rain": {}, "clouds": { "all ": 48 }, "dt ": 1463923088 , "sys" : { "type": 3 , "id" : 187827 , "message" : 0.0145 , "country" : "CN" , "sunrise" : 1463866709 , "sunset" : 1463914799 }, "id": 1806776 , "name" : "Huizhou" , "cod" : 200 }
OK,到这一步我们来实现这个功能: 由于要访问到网络所以需要添加网络访问权限:
<uses-permission android:name ="android.permission.INTERNET" />
紧接着完善刚刚提到的那个接口: 为什么是@GET(“weather”)? 我们上面提到要访问的地址为:
http:// api.openweathermap.org/data/ 2.5 /weather?q=Huizhou&APPID=f8d8ead8299f963abcded5c40c0bcb81
去除掉访问参数后的地址为:
http:// api.openweathermap.org/data/ 2.5 /weather
我们再看OpenWeather的API,其中http://api.openweathermap.org/data/2.5/ 为公共部分,最后一个是变化的,我们将http://api.openweathermap.org/data/2.5/ 作为baseUri weather作为地址的区别部分。这里需要注意的是baseuri一定要以’/‘结尾,GET(“weather”)这个不能以/开头,刚开始使用的时候由于这个原因导致了获取不到返回值,具体为什么,我将会在介绍完这个例子后给大家介绍下。
public interface IDouWheather { @GET ("weather" ) Call<WheatherResult> getWheatherResult(@Query ("q" ) String cityName, @Query ("APPID" ) String ApiId); }
关于访问接口还有如下的写法,这里介绍的是Path的用法。
public interface GitHub { @GET ("/repos/{owner}/{repo}/contributors" ) Call<List<Contributor>> contributors(@Path ("owner" ) String owner,@Path ("repo" ) String repo); }
String baseUrl = "http://api.openweathermap.org/data/2.5/" ;Retrofit retrofit = new Retrofit .Builder()
Gson: com.squareup.retrofit2:converter-gson
Jackson: com.squareup.retrofit2:converter-jackson
Moshi: com.squareup.retrofit2:converter-moshi
Protobuf: com.squareup.retrofit2:converter-protobuf
Wire: com.squareup.retrofit2:converter-wire
Simple XML:com.squareup.retrofit2:converter-simplexml
*/ .addConverterFactory(GsonConverterFactory.create () ) .baseUrl(baseUrl ) .build() ; IDouWheather weatherService = retrofit.create(IDouWheather .class ); Call<WheatherResult> call = weatherService.getWheatherResult("Huizhou" , "f8d8ead8299f963abcded5c40c0bcb89" ) ; call.enqueue(new Callback<WheatherResult>() { @Override public void onResponse(Call<WheatherResult> call , Response<WheatherResult> response ) { if (response.isSuccess() ) { WheatherResult result = response.body() ; Log . i("xiaohai.lin" , "getName = " + result.getName() ); Log . i("xiaohai.lin" , "getTemp = " + result.getMain() .getTemp() ); Log . i("xiaohai.lin" , "getLat = " + result.getCoord() .getLat() ); Log . i("xiaohai.lin" , "getLon = " + result.getCoord() .getLon() ); Log . i("xiaohai.lin" , "getDescription = " + result.getWeather() .get(0 ).getDescription() ); } } @Override public void onFailure(Call<WheatherResult> call , Throwable t ) { } });
下面是返回数据对应的Bean,这个我是使用GSONFormat插件自动生成的:注意这里可以不用实现全部的节点,但是一定要注意,参数名一定要和返回的json数据的key一致:
public class WheatherResult { private CoordBean coord; private String base; private MainBean main; private WindBean wind; private RainBean rain; private CloudsBean clouds; private int dt; private SysBean sys; private int id; private String name; private int cod; private List <WeatherBean > weather; public CoordBean getCoord ( ) { return coord; } public void setCoord (CoordBean coord ) { this .coord = coord; } public String getBase ( ) { return base; } public void setBase (String base ) { this .base = base; } public MainBean getMain ( ) { return main; } public void setMain (MainBean main ) { this .main = main; } public WindBean getWind ( ) { return wind; } public void setWind (WindBean wind ) { this .wind = wind; } public RainBean getRain ( ) { return rain; } public void setRain (RainBean rain ) { this .rain = rain; } public CloudsBean getClouds ( ) { return clouds; } public void setClouds (CloudsBean clouds ) { this .clouds = clouds; } public int getDt ( ) { return dt; } public void setDt (int dt ) { this .dt = dt; } public SysBean getSys ( ) { return sys; } public void setSys (SysBean sys ) { this .sys = sys; } public int getId ( ) { return id; } public void setId (int id ) { this .id = id; } public String getName ( ) { return name; } public void setName (String name ) { this .name = name; } public int getCod ( ) { return cod; } public void setCod (int cod ) { this .cod = cod; } public List <WeatherBean > getWeather ( ) { return weather; } public void setWeather (List<WeatherBean> weather ) { this .weather = weather; } public static class CoordBean { private double lon; private double lat; public double getLon ( ) { return lon; } public void setLon (double lon ) { this .lon = lon; } public double getLat ( ) { return lat; } public void setLat (double lat ) { this .lat = lat; } } public static class MainBean { private double temp; private int pressure; private int humidity; private double temp_min; private double temp_max; public double getTemp ( ) { return temp; } public void setTemp (double temp ) { this .temp = temp; } public int getPressure ( ) { return pressure; } public void setPressure (int pressure ) { this .pressure = pressure; } public int getHumidity ( ) { return humidity; } public void setHumidity (int humidity ) { this .humidity = humidity; } public double getTemp_min ( ) { return temp_min; } public void setTemp_min (double temp_min ) { this .temp_min = temp_min; } public double getTemp_max ( ) { return temp_max; } public void setTemp_max (double temp_max ) { this .temp_max = temp_max; } } public static class WindBean { private double speed; private int deg; public double getSpeed ( ) { return speed; } public void setSpeed (double speed ) { this .speed = speed; } public int getDeg ( ) { return deg; } public void setDeg (int deg ) { this .deg = deg; } } public static class RainBean { } public static class CloudsBean { private int all; public int getAll ( ) { return all; } public void setAll (int all ) { this .all = all; } } public static class SysBean { private int type ; private int id; private double message; private String country; private int sunrise; private int sunset; public int getType ( ) { return type ; } public void setType (int type ) { this .type = type ; } public int getId ( ) { return id; } public void setId (int id ) { this .id = id; } public double getMessage ( ) { return message; } public void setMessage (double message ) { this .message = message; } public String getCountry ( ) { return country; } public void setCountry (String country ) { this .country = country; } public int getSunrise ( ) { return sunrise; } public void setSunrise (int sunrise ) { this .sunrise = sunrise; } public int getSunset ( ) { return sunset; } public void setSunset (int sunset ) { this .sunset = sunset; } } public static class WeatherBean { private int id; private String main; private String description; private String icon; public int getId ( ) { return id; } public void setId (int id ) { this .id = id; } public String getMain ( ) { return main; } public void setMain (String main ) { this .main = main; } public String getDescription ( ) { return description; } public void setDescription (String description ) { this .description = description; } public String getIcon ( ) { return icon; } public void setIcon (String icon ) { this .icon = icon; } } }
点击运行就可以直接获取返回的结果了。
基本用法: Retrofix && RxJava: 使用RXJava会使得整个流程会显得更加清晰,在原先项目中加入RxJava步骤很简单只需要在原有的基础上作如下改动即可:
在build.gradle中加入:
compile 'io.reactivex:rxjava:1 .1 .0 'compile 'io.reactivex:rxandroid:1 .1 .0 'compile 'com.squareup.retrofit2:adapter-rxjava:2 .0 .0 -beta4'
这时候接口就不能是Call了,而应该是Observable:
public interface IDouMusic { @GET ("weather" ) Observable<WheatherResult> getWheatherResult(@Query ("q" ) String cityName, @Query ("APPID" ) String ApiId); }
String baseUrl = "http://api.openweathermap.org/data/2.5/" ; Retrofit retrofit = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create () ) .addCallAdapterFactory(RxJavaCallAdapterFactory.create () ) .baseUrl(baseUrl ) .build() ; IDouMusic weatherService = retrofit.create(IDouMusic .class ); Observable<WheatherResult> observable = weatherService.getWheatherResult("Huizhou" , "f8d8ead8299f963abcded5c40c0bcb89" ) ; observable.subscribeOn(Schedulers.io () ) .observeOn(AndroidSchedulers.mainThread () ) .subscribe(new Subscriber<WheatherResult>() { @Override public void onCompleted() {} @Override public void onError(Throwable e ) {} @Override public void onNext(WheatherResult wheatherResult ) { Log . i("xiaohai.lin" , "getName = " + wheatherResult.getName() ); Log . i("xiaohai.lin" , "getTemp = " + wheatherResult.getMain() .getTemp() ); Log . i("xiaohai.lin" , "getLat = " + wheatherResult.getCoord() .getLat() ); Log . i("xiaohai.lin" , "getLon = " + wheatherResult.getCoord() .getLon() ); Log . i("xiaohai.lin" , "getDescription = " + wheatherResult.getWeather() .get(0 ).getDescription() ); } });
Retrofix && Realm: Realm 可以与 Retrofit 1.x 和 2.x 无缝配合工作。但注意 Retrofit 不会自动将对象存入 Realm。 你需要通过调用 Realm.copyToRealm() 或 Realm.copyToRealmOrUpdate() 来将它们存入 Realm。
GitHubService service = restAdapter.create(GitHubService .class ); List<Repo> repos = service.list Repos("octocat" ) ; realm.begin Transaction() ; List<Repo> realmRepos = realm.copyToRealmOrUpdate(repos ) ; realm.commitTransaction() ;
Retrofix2 新特性: http://api.openweathermap.org/data/2.5/weather?q=Huizhou&APPID=f8d8ead8299f963abcded5c40c0bcb89 https://gank.io/post/56e80c2c677659311bed9841 https://yq.aliyun.com/articles/26705
http://www.07net01.com/program/2016/02/1307334.html http://www.jianshu.com/p/c1a3a881a144 https://twiceyuan.com/2015/12/26/retrofit2-0/?utm_source=tuicool&utm_medium=referral http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0915/3460.html http://blog.csdn.net/liuhongwei123888/article/details/50375283 http://www.cnblogs.com/angeldevil/p/3757335.html http://www.bkjia.com/Androidjc/995850.html http://blog.csdn.net/lizelinll/article/details/42361327 http://www.tuicool.com/articles/6zIvQbb http://www.tuicool.com/articles/fQju2uQ http://blog.csdn.net/tiankong1206/article/details/46486401 http://blog.csdn.net/caroline_wendy/article/details/50557470
http://www.cxbiao.com/2016/05/14/Retrofit2%E4%B8%8ERxJava%E7%94%A8%E6%B3%95%E8%A7%A3%E6%9E%90/ http://www.jcodecraeer.com/plus/view.php?aid=3460