部分參考了作者 飛奔的螞蟻
初識rxAndroid
1.rxAndroid涉及對象:訂閱者(觀察者),被觀察者以及訂閱事件
訂閱者與觀察者
被觀察者可以理解為數據源,它可以向訂閱者(觀察者)發送數據消息和消息,而訂閱者則通過被觀察者發送的消息做出相應的動作。而rxAndroid本身也提供了線程切換的API,可以分別指定訂閱者和被觀察者的線程。
每一段rxAndroid代碼都從被觀察者開始
observables 被觀察者(事件源)
subscribers 觀察者 訂閱者
schedulers 子線程、主線程切換的調度 器,
schedulers.newThread() 在子線程中執行,
schedulers.mainThread()在主線程中執行,
schedulers.io(),訪問網絡和數據操作的線程執行
核心代碼
Observable.subscribe(Subcribe);
其中被觀察者通過call回調subscriber.onNext(數據)和onComplete()傳遞數據,而subcscriber實現onNext(數據){....},加上線程控制從而實現異步任務處理。
下面舉個栗子:從網絡獲取json數據:
package com.example.rxtest;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import butterknife.BindView;
import butterknife.ButterKnife;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@BindView(R.id.btn_search)
Button btnSearch;
@BindView(R.id.tv_result)
TextView tvResult;
String requestUrl = "http://www.cnblogs.com/whoislcj/p/5520384.html";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
btnSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
createSubscription();
}
});
}
private void createSubscription() {
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
String s = loadText();
subscriber.onNext(s);
subscriber.onCompleted();
}
})//被觀察者
.subscribeOn(Schedulers.io())//指定上面的被觀察者在io線程(階級數據、訪問網絡)
.observeOn(AndroidSchedulers.mainThread())//指定下面的訂閱者的線程(UI線程)
.subscribe(new Subscriber<String>() {//訂閱者
@Override
public void onStart() {
tvResult.setText("開始加載..");
}
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
tvResult.setText("加載出錯" + e.getMessage());
}
@Override
public void onNext(String s) {
//被觀察者onnext傳遞過來的消息
tvResult.setText(s);
}
});
}
private String loadText() {
// 新建一個URL對象
URL url = null;
String result = null;
try {
url = new URL(requestUrl);
// 打開一個HttpURLConnection連接
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
// 設置連接主機超時時間
urlConn.setConnectTimeout(5 * 1000);
//設置從主機讀取數據超時
urlConn.setReadTimeout(5 * 1000);
// 設置是否使用緩存 默認是true
urlConn.setUseCaches(true);
// 設置為Get請求
urlConn.setRequestMethod("GET");
//urlConn設置請求頭信息
//設置請求中的媒體類型信息。
urlConn.setRequestProperty("Content-Type", "application/json");
//設置客戶端與服務連接類型
urlConn.addRequestProperty("Connection", "Keep-Alive");
// 開始連接
urlConn.connect();
// 判斷請求是否成功
if (urlConn.getResponseCode() == 200) {
// 獲取返回的數據
result = streamToString(urlConn.getInputStream());
Log.e(TAG, "Get方式請求成功,result--->" + result);
} else {
Log.e(TAG, "Get方式請求失敗");
}
// 關閉連接
urlConn.disconnect();
} catch (Exception e) {
Log.e(TAG, e.toString());
}
return result;
}
private String streamToString(InputStream inputStream) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuffer buffer = new StringBuffer();
String line;
try {
while ((line = bufferedReader.readLine()) != null){
buffer.append(line);
}
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
return buffer.toString();
}
}
如圖
rxAndroid操作符
map操作符
map 用來操作observable和最終的subscriber之間修改observable發出事件的類型,比如發出類型為int類型,最終為String類型,中間用map來轉換
from操作符
將其他種類的對象和數據類型轉換為Observable
當你使用Observable時,如果你要處理的數據都可以轉換成展現為Observables,而不是需要使用Observables和其他類型的數據
/**
* 使用在被觀察者,返回的對象一般都是數值類型
*/
public static void from(){
Integer [] items={1,2,3,4,5,6,7,8,9};
Observable observable = Observable.from(items);
observable.subscribe(new Action1() {
@Override public void call(Object o) {
Log.i("adu",o.toString());
}
});
}
interval操作符
interval操作符既可以延遲執行一段邏輯
/**
* 指定某一時刻進行數據發送
*/
public static void interval(){
Integer [] items = {1,2,3,4,5};
Observable observable = Observable.interval(items,1, TimeUnit.SECONDS);//每隔一秒發送數據
observable.subscribe(new Action1() {
@Override public void call(Object o) {
Log.i("adu",o.toString());
}
});
}
just
獲取輸入數據, 直接分發, 更加簡潔, 省略其他回調.
/**
* 處理數組集合
*/
public static void just(){
Integer[] items1={1,2,3,4,5};
Integer[] items2={4,5,1,6,0};
Observable observable = Observable.just(items1,items2);
observable.subscribe(new Subscriber<Integer[]>() {
@Override public void onCompleted() {
Log.i("adu","onCompleted");
}
@Override public void onError(Throwable e) {
Log.i("adu","onError");
}
@Override public void onNext(Integer[] integers) {
for (int i= 0;i<integers.length;i++){
Log.i("adu","onNext==》》"+integers[i]);//先打印items1再打印items2
}
}
});
}
range操作符
range操作符的作用根據出入的初始值n和數目m發射一系列大于等于n的m個值。
/**
* 指定輸出數據的范圍
*/
public static void range(){
Observable observable = Observable.range(23,4);
observable.subscribe(new Subscriber<Integer>() {
@Override public void onCompleted() {
Log.i("adu","onCompleted");
}
@Override public void onError(Throwable e) {
Log.i("adu","onError");
}
@Override public void onNext(Integer integer) {
Log.i("adu","onNext==》》"+integer);
}
});
}
flter操作符
數據過濾器,比如得到大于或者小于某個數的值
/**
* 過濾某些條件
*/
public static void filter(){
Observable observable = Observable.just(1,2,3,4,5,6,7,8);
observable.filter(new Func1<Integer,Boolean>() {
@Override public Boolean call(Integer integer) {
return integer<5;
}
}).observeOn(Schedulers.io()).subscribe(new Subscriber<Integer>() {
@Override public void onCompleted() {
Log.i("adu","onCompleted");
}
@Override public void onError(Throwable e) {
Log.i("adu","onError");
}
@Override public void onNext(Integer integer) {
Log.i("adu","inNext==》》"+integer);
}
});
}
take操作符
獲取數據前幾位值
takelast操作符
獲取數據后幾位值
deitinct
對一個值只處理一次
等等操作,詳情參考rxAndroid操作
CompositeSubscription
用于訂閱者的管理,一般在baseActivity中創建,將所有訂閱者添加到CompositeSubcription中集中管理.
add()添加訂閱者
clear()清理訂閱者,可以再次使用
unsubscribe()取消訂閱者,再也不能使用