您的位置:首页 > 理论基础 > 计算机网络

RxAndroid+OKHttp进行网络请求

2016-09-19 12:23 447 查看
Rx(Reactive Extensions)指响应式编程,本质是观察者模式,是以观察者和订阅者为基础的异步响应方式,它是一种编程思想的突破。
 
Rxandroid有四个基本的概念:Observable(被观察者)、Observer(观察者)、subscribe(订阅)、事件。
Observer Observable Subscribe 关键是这三个类以及其中方法的使用。
如何创建观察者、被观察者、如何订阅事件?
 
基本原理:
1)Observable对象通过调用subscribe(new Subscriber{ })方法与观察者实现订阅关系.subscribe()方法将观察者和被观察者联结起来.
2)编写的工具类,只是为了获取Observable被观察者对象.
3)在被观察者中,通过OKHttp进行常规的网络访问操作.
4)观察者的回调方法 onNext()、onComplete()、onError()
onNext(T)被观察者调用这个方法发送数据,方法的参数就是Observable发送的数据,这个方法可以被调用多次.

onComplete()当被观察者遇到错误,或者无法返回期望的数据时就会调用这个方法,这个调用会终止被观察者,后续不会再调用onNext()和onComplete().onError()方法的参数,就是抛出的异常.
onComplete() 正常终止,如果没有遇到错误,被观察者在最后一次调用onNext()方法之后调用此方法.
5)在创建被观察者的create()方法里面,检查观察者的订阅状态isUnsubscribed,以便在没有观察者的时候,让被观察者停止发送数据.
6)被观察者决定什么时候触发事件以及触发怎样的事件,Rxjava使用Create()方法来创建一个被观察者,并为他定义事件触发规则. 当网络请求拿到结果的时候,触发事件,发送数据给观察者
subscriber.onNext(response.body().string());

观察者模式面向的需求是:A对象(观察者)对B对象(被观察者)的某种变化高度敏感,需要在B变化的一瞬间做出反应。

RxAndroid最核心的两个东西是Observables(被观察者,事件源)和Subscribers(订阅者)。Observables发出一系列事件,Subscribers处理这些事件。这里的事件可以是任何你感兴趣的东西,触摸事件,web接口调用返回的数据等等。
普通的异步编程方式存在的问题:
访问网络接口调用返回数据,尤其是在使用接口回调时,处理数据很麻烦。

案例一:下载图片
Activity中的代码:

package com.crs.demo.ui.rx;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import com.crs.demo.R;
import com.crs.demo.base.BaseActivity;
import com.crs.demo.constant.UrlConstant;
import com.crs.demo.utils.LogUtils;

import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
* Created on 2016/9/19.
* Author:crs
* Description:使用RxAndroid+OKHttp进行图片的下载
*/
public class RxDownLoadImgActivity extends BaseActivity implements View.OnClickListener {

private static String TAG = RxDownLoadImgActivity.class.getSimpleName();
private Button btn_rx_download_img;
private ImageView iv_rx_download_img;
private DownloadUtils mDownloadUtils;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rx_download_img);

initViews();
initListener();

//持有网络请求类的引用
mDownloadUtils = new DownloadUtils();
}

private void initViews() {
btn_rx_download_img = findView(R.id.btn_rx_download_img);
iv_rx_download_img = findView(R.id.iv_rx_download_img);
}

private void initListener() {
btn_rx_download_img.setOnClickListener(this);
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_rx_download_img: {
//观察者和被观察者通过subscribe()方法实现绑定
mDownloadUtils.downloadImage(UrlConstant.IMAGE_URL)
.subscribeOn(Schedulers.io())//IO操作
.observeOn(AndroidSchedulers.mainThread())//切换到主线程里面
.subscribe(new Subscriber<byte[]>() {
@Override
public void onCompleted() {
//主要用于处理加载对话框的显示与隐藏
}

@Override
public void onError(Throwable e) {
LogUtils.e(TAG, e.getMessage());

}

@Override
public void onNext(byte[] bytes) {
//从服务器端获取的字节数组对象,通过BitmapFactory把字节数组转化成Bitmap对象
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
iv_rx_download_img.setImageBitmap(bitmap);
}
});
}
break;
}
}

}


DownloadUtils中的代码:

package com.crs.demo.ui.rx;

import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;

import java.io.IOException;

import rx.Observable;
import rx.Subscriber;

/**
* Created on 2016/9/19.
* Author:crs
* Description:下载工具类
*/
public class DownloadUtils {

private OkHttpClient httpUtils;

public DownloadUtils() {
httpUtils = new OkHttpClient();
}

/**
* 定义下载方法,使用rx的编程思想
*
* @param url
* @return
*/
public Observable<byte[]> downloadImage(final String url) {
//创建被观察者
return Observable.create(new Observable.OnSubscribe<byte[]>() {
@Override
public void call(final Subscriber<? super byte[]> subscriber) {
//判断观察者和被观察者是否存在订阅关系
if (!subscriber.isUnsubscribed()) {
Request request = new Request.Builder().url(url).build();
httpUtils.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
subscriber.onError(e);
}

@Override
public void onResponse(Response response) throws IOException {
if (response.isSuccessful()) {
//拿到结果的一瞬间触发事件,并传递数据给观察者
//把请求结果转化成字节数组
byte[] bytes = response.body().bytes();
subscriber.onNext(bytes);
}
//数据发送已经完成
subscriber.onCompleted();
}
});

}
}
});

}

}


案例二:查询订单数据操作

Activity中的代码:

package com.crs.demo.ui.rx;

import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.crs.demo.R;
import com.crs.demo.base.BaseActivity;
import com.crs.demo.constant.UrlConstant;
import com.crs.demo.utils.ToastUtils;

import org.json.JSONException;
import org.json.JSONObject;

import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
* Created on 2016/9/19.
* Author:crs
* Description:使用RxAndroid+OKHttp进行查询数据的操作
*/
public class RxPostDataActivity extends BaseActivity implements View.OnClickListener {

private Button btn_rx_post_data;
private EditText et_rx_post_data;
private QueryUtils mQueryUtils;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rx_post_data);

initViews();
initListener();

//持有业务逻辑类的引用
mQueryUtils = new QueryUtils();

}

private void initViews() {
btn_rx_post_data = findView(R.id.btn_rx_post_data);
et_rx_post_data = findView(R.id.et_rx_post_data);

}

private void initListener() {
btn_rx_post_data.setOnClickListener(this);
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_rx_post_data: {
String orderId = et_rx_post_data.getText().toString().trim();
if (TextUtils.isEmpty(orderId)) {
return;
}

mQueryUtils.queryOrder(UrlConstant.ORDER_STATUS_POST, orderId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {

}

@Override
public void onError(Throwable e) {

}

@Override
public void onNext(String s) {
//服务器端返回的为json字符串
try {
JSONObject jsonObject = new JSONObject(s);
int code = jsonObject.getInt("Code");
if (code == 1) {
ToastUtils.showShort(RxPostDataActivity.this, "查询成功");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});

}
break;
}

}
}


QueryUtils中的代码:

package com.crs.demo.ui.rx;

import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;

import java.io.IOException;

import rx.Observable;
import rx.Subscriber;

/**
* Created on 2016/9/19.
* Author:crs
* Description:查询工具类
*/
public class QueryUtils {

private OkHttpClient httpUtils;

public QueryUtils() {
httpUtils = new OkHttpClient();
}

/**
* 定义查询操作,使用rx的编程思想
*
* @param url
* @param orderId
* @return
*/
public Observable<String> queryOrder(final String url, final String orderId) {
return Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(final Subscriber<? super String> subscriber) {
if (!subscriber.isUnsubscribed()) {
RequestBody body = new FormEncodingBuilder().add("orderNo", orderId).build();
Request request = new Request.Builder().url(url).post(body).build();
httpUtils.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
subscriber.onError(e);
}

@Override
public void onResponse(Response response) throws IOException {
if (response.isSuccessful()) {
String str = response.body().string();
subscriber.onNext(str);
}
subscriber.onCompleted();
}
});
}
}
});
}

}


响应式编程中存在大量的操作符.
From操作:
将其他种类的对象和数据类型转化成Observable;当你使用Observable时要处理的数据类型都可以转化成Observables。
 
使用RX模式的优点:
一、使用观察者模式
创建:Rx可以方便的创建事件流和数据流;
组合:Rx使用查询式的操作符组合和变换数据流;
监听:Rx可以订阅任何可观察的数据流并执行操作;
 
二、简化代码
函数式风格:
对可观察数据流使用无副作用的输入输出函数,避免了程序里错综复杂的状态。
简化代码: Rx操作符通常可以将复杂的问题简化为很少的几行代码。
异步错误处理:传统的try/catch没办法处理异步计算,Rx提供了合适的错误处理机制。
轻松使用并发:Rx的Observables和Schedulers让开发者可以摆脱底层的线程同步和各种并发问题。
 
三、操作符
Rx提供了一系列操作符,用他们来过滤filter、选择select、变换transform、结合combine和组合compose多个Observable,这些操作符让执行和符合变得非常高效。
可以把Observable当做iterable(迭代器)的推送方式的等价物,使用iterable,消费者从生产者那拉取数据,线程阻塞直至数据准备好。使用Observable,在数据准备好时,生产者将数据推送给消费者,数据同步或者一部到达,这种方式更灵活。
 
添加支持jdk1.8的代码  使用lamb
添加了一些依赖
和配置文件
使用纯java代码来实现观察者模式  定义一个接口Watcher  定义一些更改的状态
定义一个接口规范被观察者的行为
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息