例項帶你瞭解Retrofit 2.0的使用,分享目前開發Retrofit遇到的坑和心得
阿新 • • 發佈:2019-02-15
新增依賴
app/build.gradle
1
|
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta3'
|
介面呼叫
1 2 3 4 5 6 |
Retrofit retrofit = new Retrofit.Builder() //這裡建議:- Base URL: 總是以/結尾;- @Url: 不要以/開頭 .baseUrl("http://www.weather.com.cn/") .build(); ApiStores apiStores = retrofit.create(ApiStores.class); |
1
|
<uses-permission android:name="android.permission.INTERNET" />
|
同步呼叫
1 2 3 4 5 6 7 |
try { Response<ResponseBody> bodyResponse = call.execute(); String body = bodyResponse.body().string();//獲取返回體的字串 |
同步需要處理android.os.NetworkOnMainThreadException
非同步呼叫
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
call.enqueue(new Callback<ResponseBody>() { @Override public void |
移除請求
1
|
call.cancel();
|
介面引數
Path
1 2 3 4 5 6 7 8 9 |
/** * Call<T> get();必須是這種形式,這是2.0之後的新形式 * 如果不需要轉換成Json資料,可以用了ResponseBody; * 你也可以使用Call<GsonBean> get();這樣的話,需要新增Gson轉換器 */ public interface ApiStores { @GET("adat/sk/{cityId}.html") Call<ResponseBody> getWeather(@Path("cityId") String cityId); } |
Query
1 2 |
@GET("http://ip.taobao.com/service/getIpInfo.php") Call<ResponseBody> getWeather(@Query("ip") String ip); |
Body
這是針對POST方式,如果引數是json格式,如:
1 2 3 4 5 6 |
{ "apiInfo": { "apiName": "WuXiaolong", "apiKey": "666" } } |
建立Bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class ApiInfo { private ApiInfoBean apiInfo; public ApiInfoBean getApiInfo() { return apiInfo; } public void setApiInfo(ApiInfoBean apiInfo) { this.apiInfo = apiInfo; } public class ApiInfoBean { private String apiName; private String apiKey; //省略get和set方法 } } |
程式碼呼叫
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
private void getCarType() { mRetrofit = new Retrofit.Builder() .baseUrl("http://WuXiaolong.me/") .addConverterFactory(GsonConverterFactory.create()) .build(); ApiStores apiStores = mRetrofit.create(ApiStores.class); ApiInfo apiInfo = new ApiInfo(); ApiInfo.ApiInfoBean apiInfoBean = apiInfo.new ApiInfoBean(); apiInfoBean.setApiKey("666"); apiInfoBean.setApiName("WuXiaolong"); apiInfo.setApiInfo(apiInfoBean); Call<ResponseBody> call = apiStores.getCarType(apiInfo); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Response<ResponseBody> response) { String body = null;//獲取返回體的字串 try { body = response.body().string(); } catch (IOException e) { e.printStackTrace(); } Log.i("wxl", "get=" + body); } @Override public void onFailure( Throwable t) { } }); } |
ApiStores
1 2 3 4 |
public interface ApiStores { @POST("client/shipper/getCarType") Call<ResponseBody> getCarType(@Body ApiInfo apiInfo); } |
JSON解析庫
Retrofit 2現在支援許多種解析方式來解析響應資料,包括Moshi,一個由Square建立的高效JSON解析庫。
新增gson依賴
app/build.gradle
1
|
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta3'
|
jsonschema2pojo
訪問jsonschema2pojo,自動生成Java物件,如果你對gson還不熟悉,筆者建議你手動生成Java物件,感受下。
這裡如果選擇Gson,生成的程式碼中存在@Generated註解,Android預設並沒有javax.annotation library。如果你希望保留@Generated註解,需要新增如下的依賴。
1
|
compile 'org.glassfish:javax.annotation:10.0-b28'
|
或者,你可以直接刪除這個註解,完全沒有問題。筆者當然不會加這個依賴啦。
Gsonformat
作用:Android studio外掛,一般介面返回資料後要建立自己的bean,Gsonformat幫助你快速生成,不用一條一條去寫。比jsonschema2pojo更加簡單。
安裝步驟:Android studio-Settings-Plugins-搜Gsonformat-Install Plugin
效果預覽:
例項程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public class WeatherJson { //weatherinfo需要對應json資料的名稱,我之前隨便寫了個,被坑很久 private Weatherinfo weatherinfo; public Weatherinfo getWeatherinfo() { return weatherinfo; } public void setWeatherinfo(Weatherinfo weatherinfo) { this.weatherinfo = weatherinfo; } //city、cityid必須對應json資料的名稱,不然解析不了 public class Weatherinfo { private String city; private String cityid; private String temp; private String WD; private String WS; private String SD; private String WSE; private String time; private String isRadar; private String Radar; private String njd; private String qy; //這裡省略get和set方法 } } |
ApiStores:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class AppClient { static Retrofit mRetrofit; public static Retrofit retrofit() { if (mRetrofit == null) { mRetrofit = new Retrofit.Builder() .baseUrl("http://www.weather.com.cn/") .addConverterFactory(GsonConverterFactory.create()) .build(); } return mRetrofit; } public interface ApiStores { @GET("adat/sk/{cityId}.html") Call<WeatherJson> getWeather(@Path("cityId") String cityId); } } |
呼叫:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
private void getWeather() { AppClient.ApiStores apiStores = AppClient.retrofit().create(AppClient.ApiStores.class); Call<WeatherJson> call = apiStores.getWeather("101010100"); call.enqueue(new Callback<WeatherJson>() { @Override public void onResponse(Response<WeatherJson> response) { Log.i("wxl", "getWeatherinfo=" + response.body().getWeatherinfo().getCity()); } @Override public void onFailure(Throwable t) { } }); } |
經Gson轉換器,Call<ResponseBody>
換成自己要寫的Call<WeatherJson>
RxJava
依賴以下:
1 2 |
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta3' compile 'io.reactivex:rxandroid:1.0.1' |
增加addCallAdapterFactory
1 2 3 4 5 |
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://api.nuuneoi.com/base/") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); |
ApiStores
1 2 |
@GET("adat/sk/{cityId}.html") Observable<WeatherJson> getWeatherRxjava(@Path("cityId") String cityId); |
subscribe部分的程式碼在Schedulers.io被呼叫,需要把observeOn(AndroidSchedulers.mainThread())新增到連結串列中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
private void getWeatherRxjava() { AppClient.ApiStores apiStores = AppClient.retrofit().create(AppClient.ApiStores.class); Observable<WeatherJson> observable = apiStores.getWeatherRxjava("101010100"); observable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<WeatherJson>() { @Override public void onCompleted() { Log.i("wxl", "onCompleted"); } @Override public void onError(Throwable e) { Log.i("wxl", "e=" + e.getMessage()); } @Override public void onNext(WeatherJson weatherJson) { Log.i("wxl", "getWeatherinfo=" + weatherJson.getWeatherinfo().getCity()); } }); } |