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

 更新时间:2016年02月24日 15:28:12   作者:喝醉的毛毛虫  
这篇文章主要介绍了编写简易Android天气应用的代码示例,文中的例子主要是利用到了RxAndroid处理异步方法,需要的朋友可以参考下

本文所要介绍的简易天气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

相关文章

  • flutter 微信聊天输入框功能实现

    flutter 微信聊天输入框功能实现

    这篇文章主要介绍了flutter 微信聊天输入框功能实现,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  • Android自定义控件EditText使用详解

    Android自定义控件EditText使用详解

    这篇文章主要为大家详细介绍了Android自定义控件EditText的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-12-12
  • Android开发教程之shape和selector的结合使用

    Android开发教程之shape和selector的结合使用

    shape和selector是Android UI设计中经常用到的,比如我们要自定义一个圆角Button,点击Button有些效果的变化,就要用到shape和selector,接下来通过本文给大家介绍Android开发教程之shape和selector的结合使用,感兴趣的朋友一起学习吧
    2016-01-01
  • Android中关于自定义相机预览界面拉伸问题

    Android中关于自定义相机预览界面拉伸问题

    这篇文章主要为大家详细介绍了Android中关于自定义相机预览界面拉伸问题,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-02-02
  • Android 自定义View步骤

    Android 自定义View步骤

    这篇文章主要介绍了Android 自定义View步骤 的相关资料,非常不错具有参考借鉴价值,需要的朋友可以参考下
    2016-06-06
  • Android仿微信5实现滑动导航条

    Android仿微信5实现滑动导航条

    这篇文章主要为大家详细介绍了Android仿微信5实现滑动导航条,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • Android使用Notification实现通知功能

    Android使用Notification实现通知功能

    这篇文章主要为大家详细介绍了Android使用Notification实现通知功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • Android实现QQ的第三方登录和分享

    Android实现QQ的第三方登录和分享

    这篇文章主要为大家详细介绍了Android实现QQ的第三方登录和分享,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • Android TextView实现带链接文字事件监听的三种常用方式示例

    Android TextView实现带链接文字事件监听的三种常用方式示例

    这篇文章主要介绍了Android TextView实现带链接文字事件监听的方法,结合实例形式分析了链接跳转、setMovementMethod及布局属性设置三种常用的实现方式,需要的朋友可以参考下
    2017-08-08
  • Android编程之基于Log演示一个activity生命周期实例详解

    Android编程之基于Log演示一个activity生命周期实例详解

    这篇文章主要介绍了Android编程之基于Log演示一个activity生命周期,结合完整实例形式较为详细的分析总结了Log演示activity生命周期的具体用法及Log的具体使用方法,需要的朋友可以参考下
    2015-12-12

最新评论