編寫簡易Android天氣應用的代碼示例
本文所要介紹的簡易天氣App主要用RxAndroid、MVP、Retrofit實現(xiàn),首先來看看效果:
主頁內(nèi)容:

右側(cè)欄天氣列表:

左側(cè)欄城市列表

首先看看Activity主要代碼(使用MVP模式):
//調(diào)用Presenter的方法獲取數(shù)據(jù)
mMainPresenter = new MainPresenterImpl(this);
mMainPresenter.getPlaceData();
mMainPresenter.getWeatherData("成都");
//顯示主頁和右側(cè)欄天氣數(shù)據(jù)
public void setupWeatherData(WeatherResponse weatherResponse) {
if (weatherResponse == null) return;
setTitleText(DateUtils.getWeekDay(weatherResponse.date));
if (weatherResponse.results != null && weatherResponse.results.size() > 0) {
WeatherResult result = weatherResponse.results.get(0);
mTvCity.setText(getString(R.string.city, result.currentCity));
mTvPm25.setText(getString(R.string.pm25, result.pm25));
mWeatherDataAdapter.setData(result.weather_data);
mWeatherDataAdapter.notifyDataSetChanged();
mWeatherExtraAdapter.setData(result.index);
mWeatherExtraAdapter.notifyDataSetChanged();
}
}
//顯示左側(cè)欄城市列表
@Override
public void setupPlaceData(List<Place> placeList) {
if (placeList == null) {
return;
}
mPlaceAdapter.setData(placeList);
mPlaceAdapter.notifyDataSetChanged();
}
接下來看看如何在Presenter中應用RxJava、RxAndroid獲取數(shù)據(jù)
//獲取天氣數(shù)據(jù)
@Override
public void getWeatherData(String place) {
if (TextUtils.isEmpty(place)) {
return;
}
mMainView.showProgress();
ServiceManager.getInstance().getApiService().getWeatherInfo(place, Constants.BAIDU_AK)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<WeatherResponse>() {
@Override
public void onCompleted() {
Log.e(TAG, "onCompleted");
mMainView.hideProgress();
}
@Override
public void onError(Throwable e) {
Log.e(TAG, e.getMessage(), e);
mMainView.hideProgress();
}
@Override
public void onNext(WeatherResponse weatherResponse) {
mMainView.setupWeatherData(weatherResponse);
}
});
}
public interface ApiService {
/*@GET("service/getIpInfo.php")
Call<GetIpInfoResponse> getIpInfo(@Query("ip") String ip);*/
@GET("service/getIpInfo.php")
Observable<GetIpInfoResponse> getIpInfo(@Query("ip") String ip);
//http://api.map.baidu.com/telematics/v3/weather?location=%E6%88%90%E9%83%BD&output=json&ak=MPDgj92wUYvRmyaUdQs1XwCf
@GET("/telematics/v3/weather?output=json")
Observable<WeatherResponse> getWeatherInfo(@Query("location") String location, @Query("ak") String ak);
}
如上所述,我們通過百度api獲取天氣數(shù)據(jù)使用的是Retrofit框架,它能自動的返回Observable對象。
那么我們?nèi)绾瓮ㄟ^RxJava獲取本地文件中的城市列表呢?(為了方便演示,我將城市列表作為一個json字符串放于文件中)
@Override
public void getPlaceData() {
PlaceRepository repository = new PlaceRepository();
repository.getPlaceList(BaseApplication.getInstance())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<Place>>() {
@Override
public void onNext(List<Place> places) {
mMainView.setupPlaceData(places);
}
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
});
}
public class PlaceRepository {
public Observable<List<Place>> getPlaceList(final Context context) {
return Observable.create(new Observable.OnSubscribe<List<Place>>() {
@Override
public void call(Subscriber<? super List<Place>> subscriber) {
try {
AssetManager assertManager = context.getAssets();
InputStream inputStream = assertManager.open("place");
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int count = -1;
while((count = inputStream.read(data,0, 1024)) != -1) {
outStream.write(data, 0, count);
}
String json = new String(outStream.toByteArray(),"UTF-8");
Gson gson = new GsonBuilder().create();
List<Place> placeList = gson.fromJson(json, new TypeToken<List<Place>>() {}.getType());
subscriber.onNext(placeList);
} catch (Exception e) {
subscriber.onError(e);
}
subscriber.onCompleted();
}
});
}
}
通過上述代碼,我們就能完成界面所示功能了,是不是省去了Handler callback,new Thread()這些操作了,這就為什么說RxJava是用來解決Callback Hell的。
”在Activity中分別調(diào)用了獲取天氣數(shù)據(jù)和城市列表的方法,那么問題來了,如果取數(shù)據(jù)的時候顯示了process Dialog, 我該在什么時候結(jié)束呢,寫flag判斷?“
最直接的最暴力的方法就是直接在一個方法里同步調(diào)用兩個接口,那使用RxJava怎么實現(xiàn)呢?
這個問題可以使用RxJava的Merge操作符實現(xiàn),故名思議就是將兩個接口Observable合成一個,廢話不說直接上代碼:
@Override
public void getPlaceAndWeatherData(String place) {
mMainView.showProgress();
PlaceRepository repository = new PlaceRepository();
Context context = BaseApplication.getInstance();
Observable placeObservable = repository.getPlaceList(context);
Observable weatherObservable = ServiceManager.getInstance().getApiService().getWeatherInfo(place, Constants.BAIDU_AK);
Observable.merge(placeObservable, weatherObservable)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Object>() {
@Override
public void onCompleted() {
mMainView.hideProgress();
}
@Override
public void onError(Throwable e) {
mLogger.error(e.getMessage(), e);
mMainView.hideProgress();
}
@Override
public void onNext(Object obj) {
if (obj instanceof List) {
mMainView.setupPlaceData((List<Place>) obj);
} else if (obj instanceof WeatherResponse) {
mMainView.setupWeatherData((WeatherResponse) obj);
}
}
});
}
這樣就很巧妙的解決了如果取數(shù)據(jù)的時候顯示process Dialog、該在什么時候結(jié)束、寫flag判斷的問題。
如果這樣的代碼看著還不舒服,你完全可以使用Lambda,這樣可以讓代碼看起來少之又少,不過Android studio目前還不支持Lambda,如果想要使用請安裝插件RetroLambda 并且JDK 使用JDK 8以上版本.
Github源碼地址:https://github.com/mickyliu945/CommonProj
相關文章
android中SharedPreferences實現(xiàn)存儲用戶名功能
本篇文章主要介紹了android中SharedPreferences實現(xiàn)保存用戶名功能,詳細的介紹了SharedPreferences的功能,需要的朋友可以參考下2017-04-04
淺談Android中關于靜態(tài)變量(static)的使用問題
本文主要介紹了Android中關于靜態(tài)變量(static)的使用問題,具有一定的參考作用,下面跟著小編一起來看下吧2017-01-01
Android 實現(xiàn)無網(wǎng)絡傳輸文件的示例代碼
本篇文章主要介紹了Android 實現(xiàn)無網(wǎng)絡傳輸文件的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02
Android短信驗證碼監(jiān)聽解決onChange多次調(diào)用的方法
本篇文章主要介紹了Android短信驗證碼監(jiān)聽解決onChange多次調(diào)用的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-03-03
android+json+php+mysql實現(xiàn)用戶反饋功能方法解析
相信每個項目都會有用戶反饋建議等功能,這個實現(xiàn)的方法很多,下面是我實現(xiàn)的方法,供大家交流2012-11-11
Android編程連接MongoDB及增刪改查等基本操作示例
這篇文章主要介紹了Android編程連接MongoDB及增刪改查等基本操作,簡單介紹了MongoDB功能、概念、使用方法及Android操作MongoDB數(shù)據(jù)庫的基本技巧,需要的朋友可以參考下2017-07-07

