前言
很早之前就在項目中接觸到了EventBus,覺得非常的方便,在任何地方都能注冊事件,然后在任何地方都能發(fā)送,對于多個fragment,多個activity的通訊,提供了一個非常便捷的方式。
最近接觸到了LiveData,發(fā)現(xiàn)了一種更方便的方式。在android底層就實現(xiàn)了支持,配合activity和fragment的生命周期使用。當(dāng)然并不是自己想出來的,也是看了別人的教學(xué)視頻,相當(dāng)于自己做個記錄學(xué)習(xí)下吧。
LiveDataBus的封裝
LiveDataBus其實代碼上非常的簡單。依賴的包我就不贅述了,參考下
https://developer.android.google.cn/topic/libraries/architecture/livedata
應(yīng)該很多人已經(jīng)接觸過了LiveData。我就直接貼出代碼了。
package so.dian.myapplication
import androidx.lifecycle.MutableLiveData
object LiveDataBus {
private var liveMap = HashMap<String, MutableLiveData<*>>()
fun <T> with(key: String): MutableLiveData<T> {
return if (liveMap.containsKey(key)) {
liveMap[key] as MutableLiveData<T>
} else {
var liveData = MutableLiveData<T>()
liveMap[key] = liveData
liveData
}
}
fun <T> post(key: String, value: T) {
if (liveMap.containsKey(key)) {
(liveMap[key] as MutableLiveData<T>).postValue(value)
}
}
}
代碼非常的簡單,無非就是寫一個Map,保存LiveData。然后通過不同的key做區(qū)分。
如何使用
- 先注冊通過key
LiveDataBus.with<EventData>("key").observe(this, Observer {
Toast.makeText(MainActivity@ this, "接收到事件 ${it.value}", Toast.LENGTH_LONG).show()
})
- 在任意地方可以發(fā)送消息
LiveDataBus.post("key", EventData("test1", "aa"))
這里EventData是自己定義的數(shù)據(jù)類,你可以自己定義。
反射去除粘性效果
上面的使用方法,使用過EventBus和LiveData的同學(xué)應(yīng)該是分分鐘就能上手了,我就不過多贅述了。
使用過EventBus的同學(xué)肯定知道StickyEvent,粘性事件。而這里使用LiveDataBus其實默認(rèn)就有了粘性的效果。不知道粘性事件的同學(xué)可以先了解下。
https://www.cnblogs.com/fuyaozhishang/p/7968059.html
簡而言之就是,那么如果之前發(fā)送過粘性事件,你接下來第一次注冊事件的時候會馬上收到一條消息。那么有時候我們是不需要這樣的需求的。所以這里我們可以通過反射進(jìn)行修改。
首先我們要通過源碼先找到為何注冊的時候會收到一條前面發(fā)送過的消息。
這里我寫了一個Demo。有2個Activity。分別為MainActivity和Main2Activity。代碼如下
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
LiveDataBus.with<EventData>("key").observe(this, Observer {
Toast.makeText(MainActivity@ this, "接收到事件 ${it.value}", Toast.LENGTH_LONG).show()
})
bt1.setOnClickListener {
startActivity(Intent(MainActivity@ this, Main2Activity::class.java))
}
bt2.setOnClickListener {
LiveDataBus.post("key", EventData("test1", "aa"))
}
}
}
class Main2Activity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
LiveDataBus.with<EventData>("key").observe(this, Observer {
Log.e("aaaa","aaaa")
Toast.makeText(MainActivity@ this, "Main2Activity接收到事件 ${it.value}", Toast.LENGTH_LONG).show()
})
}
}

先點擊發(fā)送消息,在點擊跳轉(zhuǎn),那么一進(jìn)入Main2Activity后就會接收到事件

這邊簡單的跟下代碼,不詳細(xì)的說,有興趣的人可以自己跟一下。
按步驟發(fā)現(xiàn)
-
class MainActivity : AppCompatActivity。 - public class AppCompatActivity extends FragmentActivity
- class FragmentActivity extends ComponentActivity
protected void onCreate(@Nullable Bundle savedInstanceState) {
...
ReportFragment.injectIfNeededIn(this);
...
}
public class ReportFragment extends Fragment {
...
@Override
public void onResume() {
...
dispatch(Lifecycle.Event.ON_RESUME);
}
...
private void dispatch(Lifecycle.Event event) {
...
((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
...
...
}
public class LifecycleRegistry extends Lifecycle {
...
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
...
moveToState(next);
}
...
private void moveToState(State next) {
...
sync();
...
}
...
private void sync() {
...
backwardPass(lifecycleOwner);
...
}
...
private void backwardPass(LifecycleOwner lifecycleOwner) {
...
observer.dispatchEvent(lifecycleOwner, event);
...
}
}
...
}
static class ObserverWithState {
void dispatchEvent(LifecycleOwner owner, Event event) {
...
mLifecycleObserver.onStateChanged(owner, event);
...
}
}
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
...
activeStateChanged(shouldBeActive());
}
...
void activeStateChanged(boolean newActive) {
...
dispatchingValue(this);
...
}
...
void dispatchingValue(@Nullable ObserverWrapper initiator) {
....
considerNotify(iterator.next().getValue());
...
}
...
private void considerNotify(ObserverWrapper observer) {
....
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
...
}
好,到這里就結(jié)束了,簡單來說呢就是observer.mLastVersion<mVersion,所以觸發(fā)了onChange事件。只要利用反射把observer.mLastVersion==mVersion就成了。
先說明下原因。
mVersion是LiveData下的變量,因為是公用一個mVersion所以,mVersion其實是一直往上加的。而mLastVersion是observer下的,通過源代碼可以發(fā)現(xiàn)。
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
...
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
...
}
observer其實就是LifecycleBoundObserver。每次調(diào)用observe后都會new一個出來。所以observer.mLastVersion跳轉(zhuǎn)到第二界面的時候其實是初始化值-1.
自然就比mVersion小。
反射代碼這里就不講了。比較基礎(chǔ)。
后續(xù)
希望能夠接入RxJava可以自由切換線程,這樣能更好用