Rxjava+Retrofit+Realm的天气预报
来源:互联网 发布:印刷排版用什么软件 编辑:程序博客网 时间:2024/06/06 02:06
简要说明
本人接触rxjava、retrofit、realm时间其实也不长,学习的时候也有点疑惑,所以干脆写一个能把几个功能模块融合起来的demo,根据以往做的小demo来看,这个demo非天气预报莫属了,功能很简单,主要是获取数据、保存数据以及数据展示,和第一行代码的天气预报很类似,只是实现差别很大,这里也参考了[ Android 简易版天气预报app的实现](http://blog.csdn.net/new_one_object/article/details/51993822),写这个博客写是希望对正在学习这些框架的同学有一点点帮助。源码地址
项目介绍
首先需要在gradle里面到如下rxjava+retrofit依赖:本人的依赖包如下:compile 'io.reactivex:rxjava:1.1.0'compile 'io.reactivex:rxandroid:1.1.0'compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4'
。
realm依赖:首先是添加依赖classpath “io.realm:realm-gradle-plugin:2.2.1”,以及添加android配置apply plugin: ‘realm-android’。这里就不贴图了。
获取城市数据
本demo的天气Api是采用的聚合数据的全国天气预报接口,能免费使用500次调用,足够开发用了,只需要注册一个账号,就能拿到聚合数据的key值访问数据了,具体内容在聚合数据里有demo教你怎么访问,这里不做赘述了。这里获取数据流程是,先获取全国各个城市,然后用realm保存到数据库中,再用城市Id获取天气数据信息进行展示,从后端获取的城市json数据格式如下:
{“resultcode”:”200”,”reason”:”successed”,”result”:[{“id”:”1”,”province”:”北京”,”city”:”北京”,”district”:”北京”},{“id”:”2”,”province”:”北京”,”city”:”北京”,”district”:”海淀”}..,],”error_code”:0}
贴出来主要是为了将相应数据封装成javaBean方便在retrofit中直径进行数据转换。由于数据格式是固定code、reson、result、errorCode,而result数据类型会有所不同,所以要将整体返回结果用泛型先封装,下面的JsonResuly是对城市数据result的封装,泛型封装如下:
public class HttpResult<T>{ public int resultcode; public String reason; public T result; public int error_code;}
返回全国城市数据的泛型T 也就是result封装如下:`public class JsonResuly {private Integer id;private String province;private String city;private String district;public JsonResuly(){}public Integer getId() { return id;}public void setId(Integer id) { this.id = id;}public JsonResuly(Integer id, String province, String city, String district) { this.id = id; this.province = province; this.city = city; this.district = district;}
然后编写服务接口,因为rxjava与retrofit结合后,接口返回不再是call,而是 Observable了,这里利用上面封装的数据类型,写一个接口。
public interface WeatherService { @GET("weather/citys") //这里的key指的是从聚合数据上注册后拿到的key,必须有这个key才可以访问到数据 Observable<HttpResult<ArrayList<JsonResuly>>> getTopMovie(@Query("key") String key); }
然后为rxjava封装好一个帮助类,用于获取数据,以及将数据写入到数据库当中,帮助类如下:
public class HttpMethods { //聚合数据提供的Url public static final String BASE_URL = UrlUtils.City_Url; private static final int DEFAULT_TIMEOUT = 5; private Retrofit retrofit; private WeatherService movieService; private Context context; private static HttpMethods INSTANCE; private Realm myRealm=null; //构造方法私有 private HttpMethods(Context context) { this.context=context; //手动创建一个OkHttpClient并设置超时时间 OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); retrofit = new Retrofit.Builder() .client(httpClientBuilder.build()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .baseUrl(BASE_URL) .build(); movieService = retrofit.create(WeatherService.class); }//单例模式拿到帮助类实例 public static HttpMethods singleton(Context context) { synchronized (HttpMethods.class) { if( INSTANCE == null) { INSTANCE = new HttpMethods(context); } INSTANCE.context = context; return INSTANCE; } }//realm的初始化,获取到realm对象采可以操作对应的数据库表 public Realm getRealm(Context context) { byte[] key = new byte[64]; new SecureRandom().nextBytes(key); Realm.init(context); RealmConfiguration config = new RealmConfiguration.Builder() .name("realmdb.realm") //文件名 .schemaVersion(0) //版本号 .deleteRealmIfMigrationNeeded()//声明版本冲突时自动删除原数据库(当调用了该方法时,上面的方法将失效)。 .build();//创建 return Realm.getInstance(config); } //将获取到的数据添加到数据库当中 public void addNote(Realm realm,HttpResult<ArrayList<JsonResuly>> arrayListHttpResult){ City city=null; realm.beginTransaction();//必须先开启事务 ArrayList<JsonResuly> result=arrayListHttpResult.result; for(int i=0;i<result.size();i++){ city= new City(); city.setId(i); city.setCity_name(result.get(i).getCity()); city.setProvince_name(result.get(i).getProvince()); city.setDistrict_name(result.get(i).getDistrict()); city.setCode(result.get(i).getId()); realm.copyToRealmOrUpdate(city); city=null; } realm.commitTransaction();//提交事务 City dog = realm.where(City.class).equalTo("id", 45).findFirst(); }//为下面跳转界面时获取到对应的下一层数据 public ArrayList<String> getData(){ myRealm=getRealm(context); RealmResults<City> dogs = myRealm.where(City.class).findAll(); ArrayList<String> cities=new ArrayList<>(); String name=null; for(City city:dogs){ if(name==null){ name=city.getProvince_name(); cities.add(name); }else if(!name.equals(city.getProvince_name())){ name=city.getProvince_name(); cities.add(name); } } return cities; } //为下面跳转界面时获取到对应的下一层城市数据 public ArrayList<String> getCityData(String province){ myRealm=getRealm(context); RealmResults<City> dogs = myRealm.where(City.class).equalTo("Province_name", province).findAll(); ArrayList<String> cities=new ArrayList<String>(); String name=null; for(City city:dogs){ if(name==null){ name=city.getCity_name(); cities.add(name); }else if(!name.equals(city.getCity_name())){ name=city.getCity_name(); cities.add(name); } } return cities; } //为下面跳转界面时获取到对应的下一层市区数据 public ArrayList<String> getDistrcitData(String city){ myRealm=getRealm(context); RealmResults<City> dogs = myRealm.where(City.class).equalTo("City_name", city).findAll(); ArrayList<String> cities=new ArrayList<String>(); String name=null; for(City data:dogs){ if(name==null){ name=data.getDistrict_name(); cities.add(name); }else if(!name.equals(data.getDistrict_name())){ name=data.getDistrict_name(); cities.add(name); } } return cities; } public void getTopMovie(Subscriber<HttpResult<ArrayList<JsonResuly>>> subscriber, String key){ //这里并不是数据转换,只是将耗时任务,插入数据库操作写到了该函数中,用于在IO线程中插入数据 movieService.getTopMovie(key).flatMap(new Func1<HttpResult<ArrayList<JsonResuly>>, Observable<HttpResult<ArrayList<JsonResuly>>>>() { public Observable<HttpResult<ArrayList<JsonResuly>>> call(HttpResult<ArrayList<JsonResuly>> arrayListHttpResult) { myRealm=getRealm(context); addNote(myRealm,arrayListHttpResult); return Observable.just(arrayListHttpResult); } }) .subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(subscriber); }
最后在mainActivity中调用方法即可。这里的数据显示是用的Recycleview代码如下:
public class MainActivity extends AppCompatActivity { private TextView resultTV; private Subscriber<HttpResult<ArrayList<JsonResuly>>> subscriber; private Boolean IsFirstStart=false; private RecyclerView ry_province; private ArrayList<String> mProvince; private MyRecyclerAdapter recycleAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); resultTV = (TextView) findViewById(R.id.tv_content); ry_province=(RecyclerView)findViewById(R.id.ry_province); getMovie(); resultTV.setText("中国"); mProvince= HttpMethods.singleton(getApplicationContext()).getData(); recycleAdapter= new MyRecyclerAdapter(MainActivity.this ,mProvince); LinearLayoutManager layoutManager = new LinearLayoutManager(this); //设置布局管理器 ry_province.setLayoutManager(layoutManager); //设置为垂直布局,这也是默认的 layoutManager.setOrientation(OrientationHelper.VERTICAL); ry_province.addItemDecoration(new MyDecoration(this, MyDecoration.VERTICAL_LIST)); //设置Adapter recycleAdapter.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(View view, int position) { String province=mProvince.get(position); Intent intent=new Intent(MainActivity.this, CityActivity.class); intent.putExtra("province",province); startActivity(intent); } }); ry_province.setAdapter( recycleAdapter); } private void getMovie() { //第一次就从网上获取数据,以后的数据读取都在数据库中拿就可以了 if (IsFirstStart) { subscriber = new Subscriber<HttpResult<ArrayList<JsonResuly>>>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { Toast.makeText(getApplicationContext(), "获取数据失败", Toast.LENGTH_LONG).show(); } @Override public void onNext(HttpResult<ArrayList<JsonResuly>> arrayListHttpResult) { resultTV.setText(arrayListHttpResult.result.get(0).getCity()); } }; HttpMethods.singleton(this).getTopMovie(subscriber, UrlUtils.Key); IsFirsStart=true; } }}
这里已经将关键获取数据和存入数据查询数据都介绍完了,后面的过程只不过是类似的封装数据、获取数据、展示数据,具体内容在我的github上具体源码地址
最后希望能帮到大家一点点。
- Rxjava+Retrofit+Realm的天气预报
- 一款纯粹的在线视频App,基于Material Design + MVP + RxJava + Retrofit + Realm
- Retrofit+Rxjava的封装
- Retrofit+RxJava的使用
- 简单的RxJava+Retrofit
- Retrofit+RXJava的使用
- 如何优雅的使用Retrofit、Rxjava、Butterknife、Material开发一款MVP模式的新闻+天气预报+妹子的Android app
- RxJava与Retrofit的封装
- MVP+Retrofit+RxJava的demo
- Retrofit+Rxjava的完美结合
- RxJava和Retrofit的介绍
- RxJava+Retrofit的Android开发
- Retrofit + RxJava 的结合使用
- Retrofit + RxJava的配合使用
- RXJava+retrofit的使用尝试
- Retrofit+RxJava的联合使用
- Retrofit+RxJava的联合使用
- RxJava+Retrofit+MVVM的封装
- 构造方法(java中跟类名一样的方法名的作用)
- 数据结构之单链表——C++模板类实现
- pentaho下载
- php邮箱找回密码功能
- Strom学习00--介绍
- Rxjava+Retrofit+Realm的天气预报
- MFC消息分类和处理方式
- 迭代器的简单理解和应用
- JAVA蓝桥杯:字符串对比
- 坚持#第139天~证明了一个真理
- extern "C" 的作用
- nodejs中npm深入理解
- smail语法
- UML类图几种关系的总结