編輯:關於Android編程
本文所要介紹的簡易天氣App主要用RxAndroid、MVP、Retrofit實現,首先來看看效果:
主頁內容:
右側欄天氣列表:
左側欄城市列表
首先看看Activity主要代碼(使用MVP模式):
//調用Presenter的方法獲取數據 mMainPresenter = new MainPresenterImpl(this); mMainPresenter.getPlaceData(); mMainPresenter.getWeatherData("成都"); //顯示主頁和右側欄天氣數據 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(); } } //顯示左側欄城市列表 @Override public void setupPlaceData(List<Place> placeList) { if (placeList == null) { return; } mPlaceAdapter.setData(placeList); mPlaceAdapter.notifyDataSetChanged(); }
接下來看看如何在Presenter中應用RxJava、RxAndroid獲取數據
//獲取天氣數據 @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獲取天氣數據使用的是Retrofit框架,它能自動的返回Observable對象。
那麼我們如何通過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中分別調用了獲取天氣數據和城市列表的方法,那麼問題來了,如果取數據的時候顯示了process Dialog, 我該在什麼時候結束呢,寫flag判斷?“
最直接的最暴力的方法就是直接在一個方法裡同步調用兩個接口,那使用RxJava怎麼實現呢?
這個問題可以使用RxJava的Merge操作符實現,故名思議就是將兩個接口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); } } }); }
這樣就很巧妙的解決了如果取數據的時候顯示process Dialog、該在什麼時候結束、寫flag判斷的問題。
如果這樣的代碼看著還不舒服,你完全可以使用Lambda,這樣可以讓代碼看起來少之又少,不過Android studio目前還不支持Lambda,如果想要使用請安裝插件RetroLambda 並且JDK 使用JDK 8以上版本.
Github源碼地址:https://github.com/mickyliu945/CommonProj
功能介紹使用文章介紹以及和Picasso的對比分析請參考Introduction to Glide, Image Loader Library for Android,
很多入手了魅藍Note 3的機友們發現,在魅藍Note3上優酷居然沒有超清視頻的選項,這對於喜歡看超清視頻的機友們而言無疑是一種折磨。這種事情小編也是郁悶了
很多品牌的Android手機都實現了圖案解鎖屏幕的功能,有些應用程序出於保護的目的也使用了圖案鎖(比如支付寶),本文將介紹一種圖案鎖的實現方式,這種實現的一個優勢在於方便
序 既然是淺析,自然也就沒有深入的地方,我也寫不出深入的地方,自己沒有用過,也不會寫出來坑人的;僅僅就是在 Android Studio 中的 Gradle