1、Rxjava的基本介绍
RxJava是基于ReactiveX使用Java语言实现的版本,ReactiveX就是”观察者模式+迭代器模式+函数式编程”,它其实是一个扩展了的观察者模式,通过使用可观察的对象序列流来表述一系列事件,观察者可以依次处理不同的对象序列。
对应的,使用ReactiveX的实现方式,在Android上面类似Rxjava的框架叫RxAndroid。
2、Rxjava的核心
RxJava最核心的两个东西就是Observables(被观察者,也就是事件源)和Observer(观察者,事件的消费者),在Rxjava中观察者Observer不是直接出现的,通常是由Subscribers(英文的意思是订阅者,观察者和订阅者傻傻分不清,其实是父类和子类,不知道为何要这样命名)继承自Observer,由Observables发出一系列的事件,Subscribers进行订阅接收并进行处理。Subscribers在整个过程充当的是观察者的角色。
3、Rxjava的使用
先新建个工程,在build.gradle里面引入rxjava
compile 'io.reactivex:rxjava:1.0.14'
compile 'io.reactivex:rxandroid:1.0.1'
使用获取天气预报测试,我们就使用新浪提供的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
布局文件activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="androidsm2.libcom.com.rxjavatest2.MainActivity">
<LinearLayout
android:layout_width="368dp"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:layout_editor_absoluteY="0dp"
tools:layout_editor_absoluteX="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#FF0000"
android:weightSum="1">
<EditText
android:id="@+id/city"
android:layout_width="275dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:gravity="center_vertical"
android:layout_height="wrap_content"
android:hint="请输入城市"
android:layout_weight="0.81" />
<Button
android:id="@+id/query"
android:layout_width="80dp"
android:layout_height="match_parent"
android:text="查询"
android:gravity="center"
android:textColor="#FFFFFF"
android:layout_gravity="center_vertical"/>
</LinearLayout>
<TextView
android:id="@+id/weather"
android:layout_width="match_parent"
android:layout_height="390dp"
android:layout_margin="10dp" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>
MainAcitivty
package androidsm2.libcom.com.rxjavatest2;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import static androidsm2.libcom.com.rxjavatest2.Utils.parseWeather;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String WEATHRE_API_URL = "http://php.weather.sina.com.cn/xml.php?city=%s&password=DJOYnieT8234jlsK&day=0";
private Button queryBtn;
private EditText cityEd;
private TextView weatherTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
queryBtn = (Button) findViewById(R.id.query);
cityEd = (EditText) findViewById(R.id.city);
weatherTv = (TextView) findViewById(R.id.weather);
queryBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
final String cityStr = cityEd.getText().toString();
if (v.getId() == R.id.query) {
rxTest(cityStr);
}
}
/**
* 获取指定城市的天气情况
*
* @param city
* @return
* @throws
*/
private String getWeather(String city) {
BufferedReader reader = null;
HttpURLConnection connection = null;
String result = "";
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);
result = buffer.toString();
Log.d("TAG", "result-->" + result);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
private void rxTest(final String cityStr){
//被观察者创建一个被观察对象,并构建一个订阅者,由订阅者回调这个执行结果
Observable<Weather> myObservable = Observable.create(new Observable.OnSubscribe<Weather>() {
@Override
public void call(Subscriber<? super Weather> subscriber) {
Weather weather = Utils.parseWeather(getWeather(cityStr));
subscriber.onNext(weather);
subscriber.onCompleted();
}
})
//被观察者在新线程
.subscribeOn(Schedulers.newThread())
//观察者在主线程
.observeOn(AndroidSchedulers.mainThread());
//订阅者Subscriber其实是继承观察者Observer
Subscriber<Weather> mySubscriber = new Subscriber<Weather>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Log.e("TAG","e-->" + e);
}
@Override
public void onNext(Weather weather) {
Log.e("TAG","weather-->" + weather);
}
};
//被观察者通过subscribe订阅关系,把事件传给订阅者(观察者)
myObservable.subscribe(mySubscriber);
}
}
这个有两行代码要特别注意的地方就是:
//被观察者在新线程
.subscribeOn(Schedulers.newThread())
//观察者在主线程
.observeOn(AndroidSchedulers.mainThread());
在4.x以上版本网络连接必须开单独的线程进行处理,否则就会报NetWorkRunInUI····的错误,所以在构造这个被观察者的时候先要处理好线程,而Schedulers类是Rxjava中非常重要的一个类。
大致过程:
1、创建一个被观察者对象,并指定被观察的数据类型是Weather对象。
2、构建观察者的时候要指定线程的执行状况,否则会报错
3、onNext()、onCompleted()和onError()是3个关键的回调方法
其他非核心代码Weather.java:
package androidsm2.libcom.com.rxjavatest2;
/**
* Created by Administrator on 2017/12/19.
* @time 2017/12/19 15:03
* @change
* @class describe
*/
public class Weather {
/**
* 城市
*/
String city;
/**
* 日期
*/
String date;
/**
* 温度
*/
String temperature;
/**
* 风向
*/
String direction;
/**
* 风力
*/
String power;
/**
* 天气状况
*/
String 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();
}
}
Utils.java
package androidsm2.libcom.com.rxjavatest2;
import android.support.annotation.Nullable;
import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
import java.io.StringReader;
/**
* Created by Administrator on 2017/12/19.
* @class describe
*/
public class Utils {
@Nullable
public static 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.city = xmlParser.nextText();
} else if("savedate_weather".equals(nodeName)){
weather.date = xmlParser.nextText();
} else if("temperature1".equals(nodeName)) {
weather.temperature = xmlParser.nextText();
} else if("temperature2".equals(nodeName)){
weather.temperature += "-" + xmlParser.nextText();
} else if("direction1".equals(nodeName)){
weather.direction = xmlParser.nextText();
} else if("power1".equals(nodeName)){
weather.power = xmlParser.nextText();
} else if("status1".equals(nodeName)){
weather.status = xmlParser.nextText();
}
break;
}
eventType = xmlParser.next();
}
return weather;
} catch(Exception e) {
e.printStackTrace();
return null;
} finally {
reader.close();
}
}
}
参考链接:
http://blog.csdn.net/Job_Hesc/article/details/45798307
http://blog.csdn.net/u010072711/article/details/51590553