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

作者:喝醉的毛毛虫 时间:2023-10-16 18:30:36 

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

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

右侧栏天气列表:

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

左侧栏城市列表

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

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

标签:Android,天气
0
投稿

猜你喜欢

  • SpringBoot+SpringCache实现两级缓存(Redis+Caffeine)

    2023-10-02 05:20:58
  • Android弹窗ListPopupWindow的简单应用详解

    2021-08-04 19:42:52
  • springboot创建线程池的两种方式小结

    2022-07-12 09:27:19
  • 详解Mybatis是如何解析配置文件的

    2023-10-15 23:23:40
  • Java关于桶排序的知识点总结

    2023-12-06 03:18:04
  • C#关键字async/await用法

    2022-04-19 03:38:13
  • C#将dll打包到程序中的具体实现

    2022-11-22 16:39:34
  • C#的WebBrowser操作frame实例解析

    2022-03-02 03:46:43
  • Java中用enum结合testng实现数据驱动的方法示例

    2021-08-04 07:44:21
  • WPF+ASP.NET SignalR实现动态折线图的绘制

    2021-11-28 08:13:43
  • C#使用Ado.Net更新和添加数据到Excel表格的方法

    2022-10-02 01:27:24
  • 10张图总结出并发编程最佳学习路线

    2021-06-03 00:40:16
  • 十分钟速懂java知识点 System类

    2022-11-25 04:19:26
  • C#封装的Sqlite访问类实例

    2022-04-28 15:38:13
  • 自定义mybatis插件如何实现sql日志打印

    2023-11-29 11:22:37
  • Android Support Annotations资料整理

    2021-09-21 13:39:33
  • AccessibilityService实现微信发红包功能

    2023-06-23 03:51:53
  • Android 跨进程通Messenger(简单易懂)

    2022-03-24 00:48:25
  • c#的sortedlist使用方法

    2023-09-22 04:58:13
  • Android实现可复用的筛选页面

    2023-02-23 09:41:27
  • asp之家 软件编程 m.aspxhome.com