首页 > 系统 > Android > 正文

编写简易Android天气应用的代码示例

2020-04-11 10:45:04
字体:
来源:转载
供稿:网友

本文所要介绍的简易天气App主要用RxAndroid、MVP、Retrofit实现,首先来看看效果:
主页内容:

2016224152122404.jpg (506×900)

右侧栏天气列表:

2016224152144520.jpg (506×900)

左侧栏城市列表

2016224152203002.jpg (506×900)

首先看看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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表