前言
很早之前就在项目中接触到了EventBus,觉得非常的方便,在任何地方都能注册事件,然后在任何地方都能发送,对于多个fragment,多个activity的通讯,提供了一个非常便捷的方式。
最近接触到了LiveData,发现了一种更方便的方式。在android底层就实现了支持,配合activity和fragment的生命周期使用。当然并不是自己想出来的,也是看了别人的教学视频,相当于自己做个记录学习下吧。
LiveDataBus的封装
LiveDataBus其实代码上非常的简单。依赖的包我就不赘述了,参考下
https://developer.android.google.cn/topic/libraries/architecture/livedata
应该很多人已经接触过了LiveData。我就直接贴出代码了。
package so.dian.myapplication
import androidx.lifecycle.MutableLiveData
object LiveDataBus {
private var liveMap = HashMap>()
fun with(key: String): MutableLiveData {
return if (liveMap.containsKey(key)) {
liveMap[key] as MutableLiveData
} else {
var liveData = MutableLiveData()
liveMap[key] = liveData
liveData
}
}
fun post(key: String, value: T) {
if (liveMap.containsKey(key)) {
(liveMap[key] as MutableLiveData).postValue(value)
}
}
}
代码非常的简单,无非就是写一个Map,保存LiveData。然后通过不同的key做区分。
如何使用
- 先注册通过key
LiveDataBus.with("key").observe(this, Observer {
Toast.makeText(MainActivity@ this, "接收到事件 ${it.value}", Toast.LENGTH_LONG).show()
})
- 在任意地方可以发送消息
LiveDataBus.post("key", EventData("test1", "aa"))
这里EventData是自己定义的数据类,你可以自己定义。
反射去除粘性效果
上面的使用方法,使用过EventBus和LiveData的同学应该是分分钟就能上手了,我就不过多赘述了。
使用过EventBus的同学肯定知道StickyEvent
,粘性事件。而这里使用LiveDataBus其实默认就有了粘性的效果。不知道粘性事件的同学可以先了解下。
https://www.cnblogs.com/fuyaozhishang/p/7968059.html
简而言之就是,那么如果之前发送过粘性事件,你接下来第一次注册事件的时候会马上收到一条消息。那么有时候我们是不需要这样的需求的。所以这里我们可以通过反射进行修改。
首先我们要通过源码先找到为何注册的时候会收到一条前面发送过的消息。
这里我写了一个Demo。有2个Activity。分别为MainActivity和Main2Activity。代码如下
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
LiveDataBus.with("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("key").observe(this, Observer {
Log.e("aaaa","aaaa")
Toast.makeText(MainActivity@ this, "Main2Activity接收到事件 ${it.value}", Toast.LENGTH_LONG).show()
})
}
}
先点击发送消息
,在点击跳转
,那么一进入Main2Activity后就会接收到事件
这边简单的跟下代码,不详细的说,有兴趣的人可以自己跟一下。
按步骤发现
-
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);
}
...
}
好,到这里就结束了,简单来说呢就是observer.mLastVersion 先说明下原因。 observer其实就是 反射代码这里就不讲了。比较基础。 希望能够接入RxJava可以自由切换线程,这样能更好用
mVersion是LiveData下的变量,因为是公用一个mVersion所以,mVersion其实是一直往上加的。而mLastVersion是observer下的,通过源代码可以发现。 @MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) {
...
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
...
}
LifecycleBoundObserver
。每次调用observe后都会new一个出来。所以observer.mLastVersion
跳转到第二界面的时候其实是初始化值-1.
自然就比mVersion
小。后续