歡迎Follow我的GitHub, 關(guān)注我的簡(jiǎn)書(shū). 其余參考Android目錄.
本文的合集已經(jīng)編著成書(shū),高級(jí)Android開(kāi)發(fā)強(qiáng)化實(shí)戰(zhàn)细办,歡迎各位讀友的建議和指導(dǎo)雪隧。在京東即可購(gòu)買(mǎi):https://item.jd.com/12385680.html
Rx是響應(yīng)式編程的意思, 本質(zhì)是觀察者模式, 是以觀察者(Observer)和訂閱者(Subscriber)為基礎(chǔ)的異步響應(yīng)方式. 在Android編程時(shí), 經(jīng)常會(huì)使用后臺(tái)線程, 那么就可以使用這種方式. 目前的異步編程方式都會(huì)導(dǎo)致一些問(wèn)題, 如
(1) Asynctasks can easily lead to memory leaks.
(2) CursorLoaders with a ContentProvider require a large amount of configuration and boilerplate code to setup.
(3) Services are intended for longer running background tasks and not fast-finishing operations, such as making a network call or loading content from a database.
RxAndroid來(lái)源于RxJava, 在RxJava的基礎(chǔ)上擴(kuò)展了一些Android的功能, 已經(jīng)發(fā)布1.0版本, 讓我們來(lái)看看怎么用吧.
本文源碼的GitHub下載地址
1. 準(zhǔn)備
新建一個(gè)HelloWorld程序. 配置build.gradle
, 添加RxAndroid庫(kù)和Lamada表達(dá)式支持, 還有ButterKnife.
plugins {
id "me.tatarka.retrolambda" version "3.2.2"
}
...
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
...
compile 'com.jakewharton:butterknife:7.0.1'
compile 'io.reactivex:rxandroid:1.0.1'
}
Lambda表達(dá)式支持不是必須的, 可以讓你代碼更加簡(jiǎn)潔, 減少匿名類(lèi)的出現(xiàn).
2. 頁(yè)面
頁(yè)面很簡(jiǎn)單, 設(shè)置三個(gè)按鈕, 觸發(fā)耗時(shí)的線程操作, 分別用主線程, Asynctasks
, Rx方式調(diào)用, 觀察ProcessBar的狀態(tài).
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context=".MainActivity"
tools:showIn="@layout/activity_main">
<Button
android:id="@+id/main_thread"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="主線程"/>
<Button
android:id="@+id/main_async"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/main_thread"
android:layout_centerHorizontal="true"
android:text="Asynctasks"/>
<Button
android:id="@+id/main_rx"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/main_async"
android:layout_centerHorizontal="true"
android:text="Rx"/>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
3. 邏輯
添加一個(gè)阻塞任務(wù), 執(zhí)行5秒, 成功反饋.
// 長(zhǎng)時(shí)間運(yùn)行的任務(wù)
private String longRunningOperation() {
try {
Thread.sleep(5000);
} catch (Exception e) {
Log.e("DEBUG", e.toString());
}
return "Complete!";
}
主線程執(zhí)行時(shí), 會(huì)導(dǎo)致UI卡頓
// 線程運(yùn)行
mThreadButton.setOnClickListener(v -> {
mThreadButton.setEnabled(false);
longRunningOperation();
Snackbar.make(mRootView, longRunningOperation(), Snackbar.LENGTH_LONG).show();
mThreadButton.setEnabled(true);
});
異步線程執(zhí)行
// 異步線程
private class MyAsyncTasks extends AsyncTask<Void, Void, String> {
@Override
protected void onPostExecute(String s) {
Snackbar.make(mRootView, s, Snackbar.LENGTH_LONG).show();
mAsyncButton.setEnabled(true);
}
@Override
protected String doInBackground(Void... params) {
return longRunningOperation();
}
}
// 異步運(yùn)行
mAsyncButton.setOnClickListener(v -> {
mAsyncButton.setEnabled(false);
new MyAsyncTasks().execute();
});
響應(yīng)式方式執(zhí)行, 使用IO線程處理, 主線程響應(yīng), 也可以使用其他線程處理, 如Schedulers.io()
處理IO的線程, Schedulers.computation()
計(jì)算的線程, Schedulers.newThread()
新創(chuàng)建的線程.
// 使用IO線程處理, 主線程響應(yīng)
Observable<String> observable = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext(longRunningOperation());
subscriber.onCompleted();
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
// 響應(yīng)式運(yùn)行
mRxButton.setOnClickListener(v -> {
mRxButton.setEnabled(false);
observable.subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
mRxButton.setEnabled(true);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
Snackbar.make(mRootView, s, Snackbar.LENGTH_LONG).show();
}
});
});
使用響應(yīng)式編程可以更好的處理內(nèi)存泄露問(wèn)題, 代碼也更加優(yōu)雅和可讀, 選擇執(zhí)行線程和監(jiān)聽(tīng)線程也更加方便. 在destroy時(shí), 可以關(guān)閉正在執(zhí)行的異步任務(wù). 還有一些其他優(yōu)勢(shì), 就參考網(wǎng)站吧.
OK, 使用響應(yīng)式這種好用的異步編程方式吧.