接觸 RxJava
有一段時間了,但總感受對於 RxJava
的使用和理解還在入門階段。一方面和本身沒有去深刻學習有關,覺得使用了一些基礎的操做符,就敢吹牛說本身掌握 RxJava
。另外一方面對RxJava
事件驅動型 的編程思想,筆者始終領悟的很差。java
我認爲單純的學習操做符,實際意義不大。事實上,筆者以前也花費了大量的時間學習操做符,到頭來發現效果不佳,由於我仍是不知道什麼時候,該正確的去使用 RxJava
操做符。我便向朋友請教,他說你能夠試着去閱讀一些 Rx
開源項目的源碼,從簡單的入手,去學習 Rx
帶來的便利,和思惟方式的改變。react
又是這位朋友,向我推薦了 RxActivityResult
。代碼量很少,很適合我學習。下面,讓咱們換種方式,去 startActiviityForResult()
。git
RxActivityResult 是 VictorAlbertos 大神的又一個 Rx
開源力做,該庫不久前的更新,現已全面支持 AndroidX
。當你已經受夠了,從 onActivityResult()
中接受來自系統(如相機),或者本身的回調數據,不妨嘗試下這個庫,讓你今後告別 onActivityResult()
。簡單介紹下這個庫的特色:github
Activity
或 Fragment
的有效實例,就能夠在任何類開啓一個 Intent
。Observable
中返回,意味着能夠繼續享受RxJava
操做符的便利。build.gradle
添加 maven
依賴。allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
}
複製代碼
build.gradle
添加 RxActivityResult
和 RxJava
的依賴。implementation 'com.github.VictorAlbertos:RxActivityResult:0.5.0-2.x'
implementation 'io.reactivex.rxjava2:rxjava:2.2.3'
複製代碼
Application
中註冊 RxActivityResult
。class MyApp : Application() {
override fun onCreate() {
super.onCreate()
RxActivityResult.register(this)
}
}
複製代碼
MainActivity
中經過點擊按鈕,跳轉至 Main2Activity
。如下是代碼示例@SuppressLint("CheckResult")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val intent = Intent(this, Main2Activity::class.java)
btnJump
.setOnClickListener {
RxActivityResult
.on(this)
.startIntent(intent)
.map {
it.data()
}
.subscribe {
val extra = it.getStringExtra("resultData")
println(extra)
}
}
}
複製代碼
Main2Activity
中,點擊按鈕回傳數據。override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
btnResult.setOnClickListener {
val intent = intent
intent.putExtra("resultData", "我是回傳的數據")
setResult(Activity.RESULT_OK, intent)
finish()
}
}
複製代碼
ok,到此一個簡單的使用就完成了。若是搭配 RxBinding
使用,可以讓本身的代碼更加 Rx
,保證這一系列操做事件流的完整性。編程
btnJump
.clicks()
.throttleFirst(500, TimeUnit.MILLISECONDS)
.map { Intent(this, Main2Activity::class.java) }
.flatMap {
RxActivityResult.on(this)
.startIntent(it)
}
.map{ it.data() }
.subscribe {
val stringExtra = it.getStringExtra("resultData")
println(stringExtra)
}
複製代碼
經過寥寥的幾行代碼,便告別了 onActivityResult()
,而且能夠接收到返回的數據。這裏先拋出兩個問題:app
Application
中爲啥要註冊。onActivityResult()
的具體實現是誰。Application
中的註冊。class MyApp:Application() {
override fun onCreate() {
super.onCreate()
RxActivityResult.register(this)
}
}
複製代碼
先簡單介紹下 ActivityLifecycleCallbacks,它是定義在 Application
中的一個接口,能夠用來監聽全部 Activity
生命週期的回調,而且優先於 Activity
生命週期的回調。使用 ActivityLifecycleCallbacks
也能夠判斷當前 App
處於前臺仍是後臺。具體的使用請自行查閱。maven
RxActivityResult.register()
其實返回的是庫做者定義的 ActivitiesLifecycleCallbacks
類。經過查看源碼得知,使用了傳入的 Application
對象去註冊監聽 Activity
的生命週期。ide
到如今也就能夠回答提出的第一個問題,在 Application
中註冊 RxActivityResult
,是爲了能夠監聽到全部 Activity
的生命週期。畢竟在 onPause
以後去 startIntent()
,是沒有意義的。源碼分析
Activity
中的具體使用RxActivityResult
.on(this) // 步驟 1
.startIntent(intent) // 步驟 2
.map { it.data }
.subscribe {
val extra = it.getStringExtra("resultData")
println(extra)
}
複製代碼
on()
傳入的 this
對象,用於判斷用戶是從 Activity
或者 Fragment
的操做startIntent()
方法,最終會調用 startHolderActivity()
。@SuppressLint("CheckResult")
private Observable<Result<T>> startHolderActivity(Request request, @Nullable OnPreResult onPreResult) {
OnResult onResult = uiTargetActivity ? onResultActivity() : onResultFragment(); // 判斷從 Activity 或者 Fragment 啓動的 Intent
request.setOnResult(onResult);
request.setOnPreResult(onPreResult);
// 設置請求對象
HolderActivity.setRequest(request);
// 從當前 Activity ,打開 HolderActivity
activitiesLifecycle.getOLiveActivity().subscribe(new Consumer<Activity>() {
@Override
public void accept(Activity activity) throws Exception {
activity.startActivity(new Intent(activity, HolderActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION));
}
});
// 返回 PublishSubject
return subject;
}
複製代碼
先看下 onResultActivity()
學習
private OnResult onResultActivity() {
return new OnResult() {
@Override
public void response(int requestCode, int resultCode, Intent data) {
if (activitiesLifecycle.getLiveActivity() == null) return;
//If true it means some other activity has been stacked as a secondary process.
//Wait until the current activity be the target activity
if (activitiesLifecycle.getLiveActivity().getClass() != clazz) {
return;
}
T activity = (T) activitiesLifecycle.getLiveActivity();
// 發射 Result 結果
subject.onNext(new Result<>(activity, requestCode, resultCode, data));
subject.onComplete();
}
@Override
public void error(Throwable throwable) {
subject.onError(throwable);
}
};
}
複製代碼
建立一個 OnResult
對象,而且在 response()
中發射 Result 結果。
Subject
既能夠是數據源 Observable
,也能夠是數據的訂閱者 Observer
。public abstract class Subject<T> extends Observable<T> implements Observer<T> {
...
}
複製代碼
經過查看源碼能夠看到,Subject
實際上仍是 Observable
,只不過它實現了 Observer
接口,能夠經過 onNext
、onComplete
、onError
方法發射和終止發射數據。做者在發射 Result
的時候,使用了 PublischSubject
,PublischSubject
的特色是: Observer
只接受被訂閱以後發射的數據。
HolderActivity
中的操做在 onCreate()
中打開真正的 Intent
對象
在 onActivityResult
中關閉 HolderActivity
,而且在 onDestroy
回傳數據
@Override
protected void onDestroy() {
super.onDestroy();
if (onResult != null)
onResult.response(requestCode, resultCode, data);
}
複製代碼
總結下大致的邏輯,比如咱們購物的流程,從京東下單買書 (startActivityForResult
),店主交待員工小王(HoldrActivity
)去倉庫查找書籍,並打包發送快遞(PublischSubject.onNext(Result())
)。快遞員送貨上門,顧客覈對購買的信息(intent.getStringExtra("resultData")
),信息無誤的話獲取購買的書籍。
經過對 RxActivityResult
庫的簡單分析,瞭解了 ActivityLifecycleCallbacks
和 PublischSubject
在三方庫中的具體使用。也認識了一些 RxJava
的操做符,如 takeWhile
過濾操做符。更重要的是,在沒有碰見 RxActivityResult
時,筆者一般都是循序漸進的在 onActivityResult()
中獲取數據,而做者的這種方式,打破了我以前的認識,原來還能夠這樣處理 onActivityResult()
數據。
當我對目前這種學習方式(使用-源碼分析-總結),所帶來的收穫沾沾自喜的時候。朋友的一番話,又警醒了我。閱讀源碼,只是進階的第一步。更重要的是,對思想的掌握,站在更高的角度去思考,爲何這樣設計。而不該該只知足於基礎的源碼分析,背後的設計思想纔是精髓。
若是隻是對源碼進行分析,按照做者的思路去撥開雲霧,獲得的進步是有限的。須要再進一步的 思考,這將是我接下來須要學習的地方。