Rxjava学习记录(一)

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值