Android开发Rxjava基础版
简介
RxJava 在 GitHub 主页上的自我介绍是 “a library for composing asynchronous and event-based programs using observable sequences for the Java VM”(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)。
Rxjava好处
android异步最为常用的有AsyncTask和Handler;为什么这里介绍Rxjava呢?它的优点在哪里呢?
一个词:简洁
根据大多数人用Rxjava之后都说Rxjava简洁。在代码量上看不出有多么简洁但是在逻辑上你会看到很简洁。
使用
首先通过一个获取到当前城市的天气的案例介绍一下Rxjava最基本的使用
准备工作
- 获取天气预报使用新浪提供的api接口:
http://php.weather.sina.com.cn/xml.php?city=%B1%B1%BE%A9&password=DJOYnieT8234jlsK&day=0
其中,city后的城市转码。
Password固定
Day为0表示当天天气,1表示第二天的天气,2表示第三天的天气,以此类推,最大为4
android studio首先导入库
compile ‘io.reactivex:rxjava:1.2.1’
compile ‘io.reactivex:rxandroid:1.2.1’
先写布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.gpsxinhao.SunRxjava">
<EditText
android:layout_margin="20dp"
android:id="@+id/edit_city"
android:layout_width="match_parent"
android:layout_height="50dp" />
<Button
android:id="@+id/bt_search"
android:layout_width="match_parent"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_height="50dp"
android:text="查询"/>
<TextView
android:id="@+id/textview"
android:layout_width="match_parent"
android:layout_margin="20dp"
android:layout_height="match_parent" />
</LinearLayout>
在activity中找到定义好的控件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sun_rxjava);
//获取控件的实例
textview = (TextView) findViewById(R.id.textview);
edit_city = (EditText) findViewById(R.id.edit_city);
bt_search = (Button) findViewById(R.id.bt_search);
}
通过新浪查询天气的API获取到xml文件是这样的
<?xml version="1.0" encoding="UTF-8"?>
<!-- published at 2016-10-19 16:13:38 -->
<Profiles>
<Weather>
<city>北京</city>
<status1>霾</status1>
<status2>小雨</status2>
<figure1>mai</figure1>
<figure2>xiaoyu</figure2>
<direction1>无持续风向</direction1>
<direction2>无持续风向</direction2>
<power1>≤3</power1>
<power2>≤3</power2>
<temperature1>22</temperature1>
<temperature2>14</temperature2>
<ssd>6</ssd>
<tgd1>21</tgd1>
<tgd2>21</tgd2>
<zwx>1</zwx>
<ktk>4</ktk>
<pollution>3</pollution>
<xcz>5</xcz>
<zho></zho>
<diy></diy>
<fas></fas>
<chy>3</chy>
<zho_shuoming>暂无</zho_shuoming>
<diy_shuoming>暂无</diy_shuoming>
<fas_shuoming>暂无</fas_shuoming>
<chy_shuoming>单层薄衫、裤薄型棉衫、长裤、针织长袖衫、长袖T恤。薄型套装、牛仔衫裤、西服套装、薄型夹克</chy_shuoming>
<pollution_l>轻度</pollution_l>
<zwx_l>最弱</zwx_l>
<ssd_l>凉爽舒适</ssd_l>
<fas_l>暂无</fas_l>
<zho_l>暂无</zho_l>
<chy_l>单衣类</chy_l>
<ktk_l>不需要开启</ktk_l>
<xcz_l>不适宜</xcz_l>
<diy_l>暂无</diy_l>
<pollution_s>对空气污染物扩散无明显影响</pollution_s>
<zwx_s>紫外线最弱</zwx_s>
<ssd_s>天气状况良好时,多到户外活动,并可适当增加户外活动时间。</ssd_s>
<ktk_s>不需要开启空调</ktk_s>
<xcz_s>洗车后当日有降水、大风或沙尘天气,不适宜洗车</xcz_s>
<gm>1</gm>
<gm_l>低发期</gm_l>
<gm_s>天气舒适,不易发生感冒;</gm_s>
<yd>5</yd>
<yd_l>不适宜</yd_l>
<yd_s>人们虽然感觉舒适,但是由于有雨,不适宜户外运动;</yd_s>
<savedate_weather>2016-10-19</savedate_weather>
<savedate_life>2016-10-19</savedate_life>
<savedate_zhishu>2016-10-19</savedate_zhishu>
<udatetime>2016-10-19 07:58:00</udatetime>
</Weather>
</Profiles>
写出获取数据的方法
/**
* 获取指定城市的天气情况
* @param city 传入需要查询的城市名称
* @return 返回查询城市的天气情况(xml形式)
* @throws
*/
private String getWeather(String city) throws Exception{
BufferedReader reader = null;
HttpURLConnection connection=null;
try {
String urlString = String.format(WEATHRE_API_URL, URLEncoder.encode(city, "GBK"));
URL url = new URL(urlString);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setReadTimeout(5000);
//连接
connection.connect();
//处理返回结果
reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"));
StringBuffer buffer = new StringBuffer();
String line="";
while(!TextUtils.isEmpty(line = reader.readLine()))
buffer.append(line);
return buffer.toString();
} finally {
if(connection != null){
connection.disconnect();
}
if(reader != null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
描述天气的been类(这里不是重点就少写点)
package com.example.gpsxinhao.entity;
/**
* 天气的实体类
* Created by smy on 2016/10/18.
*/
public class Weather {
/**
* 城市
*/
private String city;
/**
* 日期
*/
private String date;
/**
* 温度
*/
private String temperature;
/**
* 风向
*/
private String direction;
/**
* 风力
*/
private String power;
/**
* 天气状况
*/
private String status;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getTemperature() {
return temperature;
}
public void setTemperature(String temperature) {
this.temperature = temperature;
}
public String getDirection() {
return direction;
}
public void setDirection(String direction) {
this.direction = direction;
}
public String getPower() {
return power;
}
public void setPower(String power) {
this.power = power;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("城市:" + city + "\r\n");
builder.append("日期:" + date + "\r\n");
builder.append("天气状况:" + status + "\r\n");
builder.append("温度:" + temperature + "\r\n");
builder.append("风向:" + direction + "\r\n");
builder.append("风力:" + power + "\r\n");
return builder.toString();
}
}
解析xml
/**
* 解析xml获取天气情况
* @param weatherXml
* @return
*/
private Weather parseWeather(String weatherXml){
//采用Pull方式解析xml
StringReader reader = new StringReader(weatherXml);
XmlPullParser xmlParser = Xml.newPullParser();
Weather weather = null;
try {
xmlParser.setInput(reader);
int eventType = xmlParser.getEventType();
while(eventType != XmlPullParser.END_DOCUMENT){
switch (eventType){
case XmlPullParser.START_DOCUMENT:
weather = new Weather();
break;
case XmlPullParser.START_TAG:
String nodeName = xmlParser.getName();
if("city".equals(nodeName)){
weather.setCity(xmlParser.nextText());
} else if("savedate_weather".equals(nodeName)){
weather.setDate( xmlParser.nextText());
} else if("temperature1".equals(nodeName)) {
weather.setTemperature( xmlParser.nextText());
} else if("direction1".equals(nodeName)){
weather.setDirection( xmlParser.nextText());
} else if("power1".equals(nodeName)){
weather.setPower( xmlParser.nextText());
} else if("status1".equals(nodeName)){
weather.setStatus( xmlParser.nextText());
}
break;
}
eventType = xmlParser.next();
}
return weather;
} catch(Exception e) {
e.printStackTrace();
return null;
} finally {
reader.close();
}
}
采用普通的方法创建Observable
/**
* 采用普通写法创建Observable
* @param city 城市名称
*/
private void observableAsNormal(final String city){
Observable.create(new Observable.OnSubscribe<Weather>() {
@Override
public void call(Subscriber<? super Weather> subscriber) {
//1.如果已经取消订阅,则直接退出
if(subscriber.isUnsubscribed()) return;
try {
//2.开网络连接请求获取天气预报,返回结果是xml格式
String weatherXml = getWeather(city);
//3.解析xml格式,返回weather实例
Weather weather = parseWeather(weatherXml);
//4.发布事件通知订阅者
subscriber.onNext(weather);
//5.事件通知完成2
subscriber.onCompleted();
} catch(Exception e){
//6.出现异常,通知订阅者
subscriber.onError(e);
}
}
}).subscribeOn(Schedulers.newThread()) //让Observable运行在新线程中
.observeOn(AndroidSchedulers.mainThread()) //让subscriber运行在主线程中
.subscribe(new Subscriber<Weather>() {
@Override
public void onCompleted() {
//对应上面的第5点:subscriber.onCompleted();
//这里写事件发布完成后的处理逻辑
}
@Override
public void onError(Throwable e) {
//对应上面的第6点:subscriber.onError(e);
//这里写出现异常后的处理逻辑
Toast.makeText(SunRxjava.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
@Override
public void onNext(Weather weather) {
//对应上面的第4点:subscriber.onNext(weather);
//这里写获取到某一个事件通知后的处理逻辑
if(weather != null)
textview.setText(weather.toString());
}
});
}
调用
现在我们只需调用observableAsNormal(String city)方法即可;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sun_rxjava);
textview = (TextView) findViewById(R.id.textview);
edit_city = (EditText) findViewById(R.id.edit_city);
bt_search = (Button) findViewById(R.id.bt_search);
bt_search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String city = edit_city.getText().toString().trim();
if(TextUtils.isEmpty(city)){
Toast.makeText(SunRxjava.this, "城市不能为空!", Toast.LENGTH_SHORT).show();
return;
}
//采用普通写法创建Observable
observableAsNormal(city);
}
});
}
总结
通过这篇文章我们了解到了RxJava如何在android中使用,对于第一次了解Rxjava不知道你感觉怎么样,反正我是有点懵.我相信通过进一步的学习和了探讨我会深层次的知道Rxjava的牛逼之处的.