RxJava2+ Retrofit2 簡介
前言:
Retrofit:
一種 HTTP 請求的框架,使用 REST API 設計,由 RESTful Client 向 Server 發出請求。
RxJava:
其特色是可以輕鬆的切換thread,並和LiveData一樣以observer pattern處理事件。
本文會使用goole map api 做RxJava2+ Retrofit2範例。
Retrofit
簡介:
Retrofit是專為API連線而生的第三方套件,與API連線的效率非常高,最特別的是其規範的REST框架讓程式高度解耦,好寫易維護,被譽為API連線的教科書。另外它跟OkHttp同為Square公司出品,兩者可以完美整合發揮更多功能。
請求方法註解
註解 |
說明 |
@GET |
get請求 |
@POST |
post請求 |
@PUT |
put請求 |
@DELETE |
delete請求 |
@PATCH |
patch請求,是對put請求的補充,用於更新部分資源 |
@HEAD |
head請求 |
@OPTIONS |
option請求 |
@HTTP |
通用註解,可替換以上所有的註解,擁有三個屬性:method、path、hasbody |
請求參數註解
註解 |
說明 |
@Body |
多用於post請求發送非表單數據,比如以方式傳遞json格式數據 |
@Filed |
多用於post請求中表單字段,Filed、FiledMap需要FormUrlEncode結合使用 |
@FiledMap |
和Filed作用一致,用於不確定表單參數 |
@Part |
用於表單字段,part、partMap與Multipart註解結合使用,適合文件上傳 |
@PartMap |
用於表單字段,默認接受的類型是map<String,RequestBody>,可用於實現多文件上傳 |
@Path |
用於url中的占位符 |
@Query |
用於Get中指定參數 |
@QueryMap |
和Query使用類似 |
@Url |
指定請求路徑 |
RxJava
簡介:
主要特性
被觀察者(Observable) 產生事件
觀察者(Observer) 接收事件
訂閱(Subscribe) 連結Observable、Observer
線程變換
Schedulers.immediate()
當前線程
AndroidSchedulers.mainThread()
主線程
Schedulers.newThread()
新線程
schedulers.io()
IO操作線程,用於進行網路請求、讀寫文件等IO操作
Schedulers.computation()
CPU計算操作線程
使用:
(範例以google place detail api做範例)
使用前請添加依賴庫和權限請求
Gradle:
//retrofit2
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
//rxjava
implementation 'io.reactivex.rxjava2:rxjava:2.0.5'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
manifests:
<uses-permission android:name="android.permission.INTERNET" />
建立Retrofit client
public class APIServiceClient {
private static APIClient apiClient;
private static String BASE_URL = "https://maps.googleapis.com/maps/api/";
public static APIClient getInstance() {
if (apiClient == null) {
synchronized (APIServiceClient.class) {
if (apiClient == null) {
new APIServiceClient();
}
}
}
return apiClient;
}
private APIServiceClient() {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new LoggingInterceptor())
.connectTimeout(10, TimeUnit.SECONDS)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
apiClient = retrofit.create(APIClient.class);
}
}
建立傳遞參數接口
public interface APIClient {
@GET("place/details/json?")
Observable<MapPlaceData> observablePlaceDetail(@Query("placeid") String place_id,
@Query("fields") String fields,
@Query("key") String api_key,
@Query("language") String language);
@GET("directions/json?")
Observable<Object> observableDirections(@Query("origin") String origin_place,
@Query("destination") String destination_place_id,
@Query("mode") String mode,
@Query("key") String api_key,
@Query("language") String language,
@Query("sensor") boolean sensor);
@GET("directions/json?")
Observable<Object> observablePublicTransportationDirections(@Query("origin") String origin_place,
@Query("destination") String destination_place_id,
@Query("mode") String mode,
@Query("transit_mode") String transit_mode,
@Query("key") String api_key,
@Query("language") String language,
@Query("sensor") boolean sensor);
@GET("place/nearbysearch/json?")
Observable<Object> observableNearBySearch(@Query("location") String location_place,
@Query("radius") String radius,
@Query("types") String type,
@Query("key") String api_key);
@GET("place/autocomplete/json?")
Observable<Object> observableAutoComplete(@Query("input") String input,
@Query("key") String api_key,
@Query("language") String language);
}
建立數據返回的Model
public class MapPlaceData {
@SerializedName("result")
private Result result;
@SerializedName("results")
private List<Result> results;
public List<Result> getResults() {
return results;
}
public void setResults(List<Result> results) {
this.results = results;
}
public Result getResult() {
return result;
}
public void setResult(Result result) {
this.result = result;
}
public class Result {
@SerializedName("formatted_phone_number")
private String formatted_phone_number;
@SerializedName("id")
private String id;
@SerializedName("formatted_address")
private String formatted_address;
@SerializedName("name")
private String name;
@SerializedName("place_id")
private String place_id;
@SerializedName("rating")
private String rating;
@SerializedName("international_phone_number")
private String international_phone_number;
@SerializedName("website")
private String website;
@SerializedName("icon")
private String icon;
@SerializedName("types")
private List<String> types;
@SerializedName("opening_hours")
private OpeningHours opening_hours;
@SerializedName("geometry")
private Geometry geometry;
public Geometry getGeometry() {
return geometry;
}
public void setGeometry(Geometry geometry) {
this.geometry = geometry;
}
public List<String> getTypes() {
return types;
}
public void setTypes(List<String> types) {
this.types = types;
}
public String getIcon() {
return TextUtils.isEmpty(icon) ? "" : icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getWebsite() {
return TextUtils.isEmpty(website) ? "" : website;
}
public void setWebsite(String website) {
this.website = website;
}
public String getInternational_phone_number() {
return TextUtils.isEmpty(international_phone_number) ? "" : international_phone_number;
}
public void setInternational_phone_number(String international_phone_number) {
this.international_phone_number = international_phone_number;
}
public String getFormatted_address() {
return TextUtils.isEmpty(formatted_address) ? "" : formatted_address;
}
public void setFormatted_address(String formatted_address) {
this.formatted_address = formatted_address;
}
public String getFormatted_phone_number() {
return TextUtils.isEmpty(formatted_phone_number) ? "" : formatted_phone_number;
}
public void setFormatted_phone_number(String formatted_phone_number) {
this.formatted_phone_number = formatted_phone_number;
}
public String getId() {
return TextUtils.isEmpty(id) ? "" : id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return TextUtils.isEmpty(name) ? "" : name;
}
public void setName(String name) {
this.name = name;
}
public String getPlace_id() {
return TextUtils.isEmpty(place_id) ? "" : place_id;
}
public void setPlace_id(String place_id) {
this.place_id = place_id;
}
public String getRating() {
return TextUtils.isEmpty(rating) ? "" : rating;
}
public void setRating(String rating) {
this.rating = rating;
}
public OpeningHours getOpening_hours() {
return opening_hours;
}
public void setOpening_hours(OpeningHours opening_hours) {
this.opening_hours = opening_hours;
}
public class Geometry{
@SerializedName("location")
private Location location;
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
}
public class Location{
@SerializedName("lat")
private String lat;
@SerializedName("lng")
private String lng;
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;
}
public String getLng() {
return lng;
}
public void setLng(String lng) {
this.lng = lng;
}
}
public class OpeningHours {
@SerializedName("open_now")
private boolean open_now;
public boolean isOpen_now() {
return open_now;
}
public void setOpen_now(boolean open_now) {
this.open_now = open_now;
}
}
}
}
開始使用RxJava2+ Retrofit2求取google map place detail api
APIServiceClient.getInstance()
.observablePlaceDetail(place_id, "name,rating,formatted_phone_number,international_phone_number," +
"website,formatted_address,icon,type,opening_hours", api_key, "zh-TW")
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<MapPlaceData>() {
private Disposable disposable;
@Override
public void onSubscribe(Disposable d) {
Log.d("getPlaceDetail", "onSubscribe...");
disposable = d;
mView.showProgressDialog();
}
@Override
public void onNext(MapPlaceData mapPlaceData) {
Log.d("TAG", "onNext: " + new Gson().toJson(mapPlaceData));
mView.placeDetailData(new Gson().toJson(mapPlaceData));
}
@Override
public void onError(Throwable e) {
Log.d("TAG", "onError: " + e.getMessage());
}
@Override
public void onComplete() {
Log.d("TAG", "onComplete: Over!");
mView.disMissProgressDialog();
disposable.dispose();
}
});
demo 示意。call back data model請自行再parser 顯示在UI上