是否可以防止LiveData在开始观察时收到最后一个值? 我正在考虑将LiveData用作事件。
例如show message,导航事件或对话框触发器等事件,类似于EventBus。
我找到了类似And the result of command 'wc'的东西 - 但它只适用于1个观察者,而不适用于多个观察者。
答案 0 :(得分:3)
我认为在开始观察是否按原样使用LiveData时,无法防止LiveData接收到最后一个值。您可以做的是扩展ViewModel
类,并使其仅在添加观察者的情况下通知视图。
另一种选择是仅忽略回调。
向ViewModel添加一个标志。
private boolean isFirstTime = true;
public boolean getIsFirstTime() { return isFirstTime; }
public boolean onObserverAdded() { isFirstTime = false; }`
在回调中添加检查
@Override
public void onChanged(@Nullable final String newName) {
boolean ignore = ((MyViewModel)ViewModelProviders.of(MyActivity.this).get(MyViewModel.class)).getIsFirstTime();
if(ignore) return;
// Update the UI
}
添加观察者后最后调用onObserverAdded()
。
答案 1 :(得分:2)
我对RxJava有一定的经验,已经习惯于认为这种行为要求通常是Observeable
(在我们的案例中是LiveData
)的关注。与operators之类的replay()相比,有很多gist可以控制与用户实际发布的内容相比实际发出的内容(以及发出的时间)。本质上,SingleLiveEvent
也具有相同的概念。
因此,我想到了MutableLiveData
的这种经过修改的实现,称为VolatileLiveData
:
open class VolatileLiveData<T> : MutableLiveData<T>() {
private val lastValueSeq = AtomicInteger(0)
private val wrappers = HashMap<Observer<in T>, Observer<T>>()
@MainThread
public override fun setValue(value: T) {
lastValueSeq.incrementAndGet()
super.setValue(value)
}
@MainThread
public override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
val observerWrapper = ObserverWrapper(lastValueSeq, observer)
wrappers[observer] = observerWrapper
super.observe(owner, observerWrapper)
}
@MainThread
public override fun observeForever(observer: Observer<in T>) {
val observerWrapper = ObserverWrapper(lastValueSeq, observer)
wrappers[observer] = observerWrapper
super.observeForever(observerWrapper)
}
@MainThread
public override fun removeObserver(observer: Observer<in T>) {
val observerWrapper = wrappers[observer]
observerWrapper?.let {
wrappers.remove(observerWrapper)
super.removeObserver(observerWrapper)
}
}
}
private class ObserverWrapper<T>(private var currentSeq: AtomicInteger, private val observer: Observer<in T>) : Observer<T> {
private val initialSeq = currentSeq.get()
private var _observer: Observer<in T> = Observer {
if (currentSeq.get() != initialSeq) {
// Optimization: this wrapper implementation is only needed in the beginning.
// Once a valid call is made (i.e. with a different concurrent sequence), we
// get rid of it any apply the real implementation as a direct callthrough.
_observer = observer
_observer.onChanged(it)
}
}
override fun onChanged(value: T) {
_observer.onChanged(value)
}
}
首先,类似于@emandt,我已将唯一序列与每个实时值相关联-但严格地在实时数据本身的范围内。每当为实时数据设置值时,都会设置此顺序。
第二,受SingleLiveData
的启发,我在用户的观察者周围引入了包装器,这些包装器仅在顺序不同的情况下才调用该包装器(即,自订阅以来已设置 new 值)制成)。
基本上是总结,但有关完整文档,请转到我的{{3}}。
关于使用它-如果您完全控制LiveData
,请像使用VolatileLiveData
一样简单地使用MutableLiveData
。如果数据最初来自其他地方(例如房间),则可以使用Transformations.switchMap()
来“切换”到 volatile 实现。
答案 2 :(得分:2)
面对同样的问题,我创建了一些简单的kotlin扩展函数,可以轻松解决问题。
用法如下:
val liveData = MutableLiveData<String>()
liveData.value = "Hello"
val freshResult = mutableListOf<String>()
val normalResult = mutableListOf<String>()
liveData.observeForeverFreshly(Observer {
freshResult.add(it)
})
liveData.observeForever(Observer {
normalResult.add(it)
})
liveData.value = "World"
assertEquals(listOf("World"), freshResult)
assertEquals(listOf("Hello", "World"), normalResult)
基本源代码被解释为“ bllow”。
有关更多详细信息(以支持某些特殊情况,例如从Transformations.map返回的MediatorLiveData
),可以在github中查看它:livedata-ext
FreshLiveData.kt
fun <T> LiveData<T>.observeFreshly(owner: LifecycleOwner, observer: Observer<in T>) {
// extention fuction to get LiveData's version, will explain in below.
val sinceVersion = this.version()
this.observe(owner, FreshObserver<T>(observer, this, sinceVersion))
}
fun <T> LiveData<T>.observeForeverFreshly(observer: Observer<in T>, skipPendingValue: Boolean = true) {
val sinceVersion = this.version()
this.observeForever(FreshObserver<T>(observer, this, sinceVersion))
}
// Removes the observer which has been previously observed by [observeFreshly] or [observeForeverFreshly].
fun <T> LiveData<T>.removeObserverFreshly(observer: Observer<in T>) {
this.removeObserver(FreshObserver<T>(observer, this, 0))
}
class FreshObserver<T>(
private val delegate: Observer<in T>,
private val liveData: LiveData<*>,
private val sinceVersion: Int
) : Observer<T> {
override fun onChanged(t: T) {
if (liveData.version() > sinceVersion) {
delegate.onChanged(t)
}
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as FreshObserver<*>
if (delegate != other.delegate) return false
return true
}
override fun hashCode(): Int {
return delegate.hashCode()
}
}
因为我们需要访问LiveData的pcakage可见方法getVersion()
进行比较,所以请在包android.arch.lifecycle
或androidx.lifecycle
(AndroidX)中创建一个类:
LiveDataHiddenApi.kt
package androidx.lifecycle
fun LiveData<*>.version(): Int {
return this.getVersion()
}
答案 3 :(得分:2)
I`m using this EventWraper class from Google Samples inside MutableLiveData
/**
* Used as a wrapper for data that is exposed via a LiveData that represents an event.
*/
public class Event<T> {
private T mContent;
private boolean hasBeenHandled = false;
public Event( T content) {
if (content == null) {
throw new IllegalArgumentException("null values in Event are not allowed.");
}
mContent = content;
}
@Nullable
public T getContentIfNotHandled() {
if (hasBeenHandled) {
return null;
} else {
hasBeenHandled = true;
return mContent;
}
}
public boolean hasBeenHandled() {
return hasBeenHandled;
}
}
In ViewModel :
/** expose Save LiveData Event */
public void newSaveEvent() {
saveEvent.setValue(new Event<>(true));
}
private final MutableLiveData<Event<Boolean>> saveEvent = new MutableLiveData<>();
LiveData<Event<Boolean>> onSaveEvent() {
return saveEvent;
}
In Activity/Fragment
mViewModel
.onSaveEvent()
.observe(
getViewLifecycleOwner(),
booleanEvent -> {
if (booleanEvent != null)
final Boolean shouldSave = booleanEvent.getContentIfNotHandled();
if (shouldSave != null && shouldSave) saveData();
}
});
答案 4 :(得分:2)
根据jurij-pitulja的答案。
如果我们使用kotlin coroutines
,则解决方案如下所示。
class Event<T>(private val content: T) {
var isHandled = false
private set
fun getContentIfNotHandled(): T? {
return takeIf { !isHandled }?.let {
isHandled = true
content
}
}
}
在view model
类内部,将Flow.asLiveData()
替换为emit new Event
val authResult: LiveData<Event<Result<AuthResponse>>> = _emailLiveData.switchMap { email ->
liveData{
repository.authRequest(email).collect{
emit(Event(it))
}
}
}
在observer
内实现fragment
方法
viewModel.authResult.observe(viewLifecycleOwner){
it.getContentIfNotHandled()?.run {
onAuthRequestComplete(this)
}
}
答案 5 :(得分:1)
我创建了一个新类,该类将保存我的真实数据和一个“特殊ID”:
class LiveDataItem {
long mRealtimeNanos;
YOUR_PREVIOUS_LIVEDATA_TYPE mData;
LiveDataItem(YOUR_PREVIOUS_LIVEDATA_TYPE data, long realtimeNanos) {
this.mRealtimeNanos = realtimeNanos;
this.mData = data;
}
}
然后我创建了一个新的“全局”变量:
final List<Long> mExcludedRealtimeNanos = new ArrayList<>;
这时,我选择通过新的自定义“ postValue()”方法设置“ LiveDataItem”类型的“ set / postValue()”,而不是原始的“ YOUR_PREVIOUS_LIVEDATA_TYPE”类型:
public void myPostValue(YOUR_PREVIOUS_LIVEDATA_TYPE data, boolean notifyWhenObserved) {
long cRealtimeNanos = SystemClock.realtimeNanos();
if (!notifyWhenObserved) mExcludedRealtimeNanos.add(cRealtimeNanos);
....postValue(new LiveDataItem(data, cRealtimeNanos));
}
然后,我创建了一个普通的观察器,该观察器将接收所有“ Changed()”事件,并在其中放入有关“ RealtimeNanos”的检查:
public void onChanged(LiveDataItem myDataItem) {
boolean cFound = false;
for (Long cRealtimeNanos : mExcludedRealtimeNanos) {
if (cRealtimeNanos == myDataItem.mRealtimeNanos) {
cFound = true;
break;
}
}
//check if it was found --> NO: it means that I wish to get the notification
if (!cFound) mMyOnChangedCallback(myDataItem.mData)
}
很明显,“ mMyOnChangedCallback()”方法是一个回调函数,只有当您设置在数据创建期间通知它时,才会在原始“ onChanged()”事件发生时调用该函数。
您可以选择再次接收通知,方法是从“ mExcludedRealtimeNanos”中删除THAT RealtimeNanos,然后将新的Observer附加到该LiveData。
很少有更改可以改进此代码,但是我写了一些我记得的旧代码(目前我不在电脑旁)。例如,当使用自定义postValue()方法发布新数据时,我们可以决定从“ mExcludedRealtimeNanos”中删除一个值。...
答案 6 :(得分:1)
即使我有相同的要求。我通过扩展MutableLiveData实现了这一点
package com.idroidz.android.ion.util;
import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.Observer;
import android.support.annotation.MainThread;
import android.support.annotation.Nullable;
import java.util.concurrent.atomic.AtomicBoolean;
public class VolatileMutableLiveData<T> extends MutableLiveData<T> {
private final AtomicBoolean mPending = new AtomicBoolean(false);
@MainThread
public void observe(LifecycleOwner owner, final Observer<T> observer) {
// Observe the internal MutableLiveData
mPending.set(false);
super.observe(owner, new Observer<T>() {
@Override
public void onChanged(@Nullable T t) {
if (mPending.get()) {
observer.onChanged(t);
}
}
});
}
@MainThread
public void setValue(@Nullable T t) {
mPending.set(true);
super.setValue(t);
}
/**
* Used for cases where T is Void, to make calls cleaner.
*/
@MainThread
public void call() {
setValue(null);
}
public void callFromThread() {
super.postValue(null);
}
}
答案 7 :(得分:1)
我创建了一个LiveData对象FreshLiveData
,该对象仅在调用onChange
或setValue
后才向观察者发出postValue
。
FreshLiveData.kt
/**
* A lifecycle-aware observable that emits only new data after subscription. Any data that has
* already been set, before the observable has subscribed, will be ignored.
*
* This avoids a common problem with events: on configuration change (like rotation, font change) an
* update can be emitted if the observer is active. This LiveData only calls the observable if
* there's an explicit call to setValue() or postValue().
*
* All observers will be notified of change(s).
*/
class FreshLiveData<T> : MutableLiveData<T>() {
private val observers = mutableMapOf<LifecycleOwner, FreshLiveDataObserver>()
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
@Suppress("UNCHECKED_CAST")
observer as Observer<T>
observers[owner].apply {
if (this == null) {
observers[owner] = FreshLiveDataObserver(observer).apply {
super.observe(owner, this)
}
} else {
add(observer)
}
}
}
override fun observeForever(observer: Observer<in T>) {
@Suppress("UNCHECKED_CAST")
observer as Observer<T>
observers[ProcessLifecycleOwner.get()].apply {
if (this == null) {
observers[ProcessLifecycleOwner.get()] = FreshLiveDataObserver(observer).apply {
super.observeForever(this)
}
} else {
add(observer)
}
}
}
override fun removeObservers(owner: LifecycleOwner) {
observers.remove(owner)
super.removeObservers(owner)
}
override fun removeObserver(observer: Observer<in T>) {
@Suppress("UNCHECKED_CAST")
observers.forEach { it.value.remove(observer as Observer<T>) }
super.removeObserver(observer)
}
@MainThread
override fun setValue(t: T?) {
observers.forEach { it.value.setPending() }
super.setValue(t)
}
override fun postValue(value: T) {
observers.forEach { it.value.setPending() }
super.postValue(value)
}
inner class FreshLiveDataObserver(observer: Observer<T>) : Observer<T> {
private val observers = mutableSetOf<Observer<T>>()
private val pending = AtomicBoolean(false)
init {
observers.add(observer)
}
fun add(observer: Observer<T>) = observers.add(observer)
fun remove(observer: Observer<T>) = observers.remove(observer)
fun setPending() = pending.set(true)
override fun onChanged(t: T) {
if (pending.compareAndSet(true, false)) {
observers.forEach { observer ->
observer.onChanged(t)
}
}
}
}
}
这是将现有的LiveData
转换为FreshLiveData
的扩展。
LiveDataExtensions.kt
@MainThread
fun <T> LiveData<T>.toFreshLiveData(): LiveData<T> {
val freshLiveData = FreshLiveData<T>()
val output = MediatorLiveData<T>()
// push any onChange from the LiveData to the FreshLiveData
output.addSource(this) { liveDataValue -> freshLiveData.value = liveDataValue }
// then push any onChange from the FreshLiveData out
output.addSource(freshLiveData) { freshLiveDataValue -> output.value = freshLiveDataValue }
return output
}
用法:
val liveData = MutableLiveData<Boolean>()
liveData.value = false
liveData.toFreshLiveData().observeForever {
// won't get called with `it = false` because the observe was setup after setting that livedata value
// will get called with `it = true` because the observer was setup before setting that livedata value
}
liveData.value = false
val freshLiveData = FreshLiveData<Boolean>()
freshLiveData.value = false
freshLiveData.observeForever {
// won't get called with `it = false` because the observe was setup after setting that livedata value
// will get called with `it = true` because the observer was setup before setting that livedata value
}
freshLiveData.value = true
答案 8 :(得分:1)
没有理由不使用LiveData。如果您需要一个单独的行为(某种东西不会保留以前的值),那么您应该使用一个不能保留以前的值的组件-而不是乱砍它(“记住”它已经发出并忘记了)发射等等)
您可以添加event-emitter
库:
implementation 'com.github.Zhuinden:live-event:1.1.0'
来自Jitpack:maven { url "https://jitpack.io" }
那你就可以做
private val eventEmitter = EventEmitter<WordController.Events>()
val controllerEvents: EventSource<WordController.Events> = eventEmitter
和
controllerEvents.observe(viewLifecycleOwner) { event: WordController.Events ->
when (event) {
is WordController.Events.NewWordAdded -> showToast("Added ${event.word}")
}.safe()
}
答案 9 :(得分:1)
您可以使用this文章中所述的EventLiveData。与SingleLiveData一样,它是LiveData扩展,但支持多个观察者。当观察者应该接收事件时,还允许自定义生命周期限制。例如,如果您不想在片段处于后台时接收事件。
EventLiveData拥有内部观察者,该观察者可以永远观察,而覆盖了使用observe方法将观察者保存到内部地图中,而绕过了本机LiveData事件分配机制。
public class EventLiveData<T> extends LiveData<T> {
private final HashMap<Observer<? super T>, EventObserverWrapper> observers= new HashMap<>();
private final Observer<T> internalObserver;
int mActiveCount = 0;
public EventLiveData() {
this.internalObserver = (new Observer<T>() {
@Override
public void onChanged(T t) {
Iterator<Map.Entry<Observer<? super T>, EventObserverWrapper>> iterator = EventLiveData.this.observers.entrySet().iterator();
while (iterator.hasNext()){
EventObserverWrapper wrapper= iterator.next().getValue();
if(wrapper.shouldBeActive())
wrapper.getObserver().onChanged(t);
}
}
});
}
private void internalObserve(){
super.observeForever(this.internalObserver);
}
@MainThread
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
observe(owner, observer,STARTED,null);
}
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer, @NonNull Lifecycle.State minimumStateForSendingEvent) {
observe(owner, observer,minimumStateForSendingEvent,null);
}
@MainThread
public void observeInOnStart(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
observe(owner, observer,STARTED, Lifecycle.Event.ON_STOP);
}
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer, @NonNull Lifecycle.State minimumStateForSendingEvent, Lifecycle.Event removeObserverEvent) {
assertMainThread("observe");
assertNotNull(owner, "owner");
assertNotNull(observer, "observer");
assertNotNull(owner, "minimumStateForSendingEvent");
assertDestroyedState(minimumStateForSendingEvent);
assertMaximumEvent(removeObserverEvent);
if(minimumStateForSendingEvent==DESTROYED){
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
StackTraceElement caller = stackTraceElements[3];
String className = caller.getClassName();
String methodName = caller.getMethodName();
IllegalArgumentException exception =
new IllegalArgumentException("State can not be equal to DESTROYED! : " +
"method " + className + "." + methodName +
", parameter " + minimumStateForSendingEvent);
throw sanitizeStackTrace(exception);
}
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
EventLifecycleBoundEventObserver wrapper = new EventLifecycleBoundEventObserver(owner, observer);
wrapper.setMinimumStateForSendingEvent(minimumStateForSendingEvent);
wrapper.setMaximumEventForRemovingEvent(removeObserverEvent);
EventObserverWrapper existing = wrapper;
if(!observers.containsKey(observer))existing = observers.put(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
if (!super.hasObservers()) {
internalObserve();
}
}
@MainThread
@Override
public void observeForever(@NonNull Observer observer) {
assertMainThread("observeForever");
assertNotNull(observer, "observer");
EventAlwaysActiveEventObserver wrapper = new EventAlwaysActiveEventObserver(observer);
EventObserverWrapper existing = wrapper;
if(!observers.containsKey(observer))existing = observers.put(observer, wrapper);
if (existing != null && existing instanceof EventLiveData.EventLifecycleBoundEventObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
if (!super.hasObservers()) {
internalObserve();
}
wrapper.activeStateChanged(true);
}
/**
{@inheritDoc}
*/
@Override
public void removeObservers(@NonNull LifecycleOwner owner) {
assertMainThread("removeObservers");
assertNotNull(owner, "owner");
Iterator<Map.Entry<Observer<? super T>, EventObserverWrapper>> iterator = EventLiveData.this.observers.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry<Observer<? super T>, EventObserverWrapper> entry=iterator.next();
if(entry.getValue() instanceof EventLiveData.EventLifecycleBoundEventObserver){
EventLifecycleBoundEventObserver eventLifecycleBoundObserver =(EventLifecycleBoundEventObserver) entry.getValue();
if(eventLifecycleBoundObserver.isAttachedTo(owner))this.observers.remove(entry.getKey());
}
}
}
@Override
public void removeObserver(@NonNull Observer observer) {
assertMainThread("removeObserver");
assertNotNull(observer, "observer");
this.observers.remove(observer);
}
final protected void onActive() {}
protected void onActiveEvent() {}
protected void onInactive() {
}
@SuppressWarnings("WeakerAccess")
public boolean hasObservers() {
return observers.size() > 0;
}
@SuppressWarnings("WeakerAccess")
public boolean hasActiveObservers() {
return mActiveCount > 0;
}
class EventLifecycleBoundEventObserver extends EventObserverWrapper implements LifecycleObserver {
@NonNull
private final LifecycleOwner mOwner;
private Lifecycle.State MINIMUM_STATE_FOR_SENDING_EVENT= STARTED;
private Lifecycle.Event MAXIMUM_EVENT_FOR_REMOVING_EVENT= null;
EventLifecycleBoundEventObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
public Lifecycle.State getMinimumStateForSendingEvent() {
return MINIMUM_STATE_FOR_SENDING_EVENT;
}
public Lifecycle.Event getMaximumStateForRemovingEvent() {
return MAXIMUM_EVENT_FOR_REMOVING_EVENT;
}
public void setMaximumEventForRemovingEvent(Lifecycle.Event MAXIMUM_EVENT_FOR_REMOVING_EVENT) {
this.MAXIMUM_EVENT_FOR_REMOVING_EVENT = MAXIMUM_EVENT_FOR_REMOVING_EVENT;
}
public void setMinimumStateForSendingEvent(Lifecycle.State MINIMUM_STATE_FOR_SENDING_EVENT) {
this.MINIMUM_STATE_FOR_SENDING_EVENT = MINIMUM_STATE_FOR_SENDING_EVENT;
}
@Override
boolean shouldBeActive() {
Lifecycle.State state=mOwner.getLifecycle().getCurrentState();
return state.isAtLeast(MINIMUM_STATE_FOR_SENDING_EVENT);
}
@OnLifecycleEvent(Lifecycle.Event.ON_ANY)
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED||(MAXIMUM_EVENT_FOR_REMOVING_EVENT!=null&&MAXIMUM_EVENT_FOR_REMOVING_EVENT==event)) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
private abstract class EventObserverWrapper {
protected final Observer<? super T> mObserver;
boolean mActive;
EventObserverWrapper(Observer<? super T> observer) {
mObserver = observer;
}
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {
return false;
}
void detachObserver() {
}
public Observer<? super T> getObserver() {
return mObserver;
}
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
boolean wasInactive = EventLiveData.this.mActiveCount == 0;
EventLiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActiveEvent();
}
if (EventLiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
}
}
private class EventAlwaysActiveEventObserver extends EventObserverWrapper {
EventAlwaysActiveEventObserver(Observer<? super T> observer) {
super(observer);
}
@Override
boolean shouldBeActive() {
return true;
}
}
private void assertDestroyedState(@NonNull Lifecycle.State minimumStateForSendingEvent){
if(minimumStateForSendingEvent==DESTROYED){
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
StackTraceElement caller = stackTraceElements[3];
String className = caller.getClassName();
String methodName = caller.getMethodName();
IllegalArgumentException exception =new IllegalArgumentException("State can not be equal to "+ minimumStateForSendingEvent +"method " + className + "." + methodName +", parameter minimumStateForSendingEvent");
throw sanitizeStackTrace(exception);}
}
private void assertMaximumEvent(@NonNull Lifecycle.Event maximumEventForRemovingEvent){
if(maximumEventForRemovingEvent== Lifecycle.Event.ON_START||maximumEventForRemovingEvent== Lifecycle.Event.ON_CREATE
||maximumEventForRemovingEvent== Lifecycle.Event.ON_RESUME){
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
StackTraceElement caller = stackTraceElements[3];
String className = caller.getClassName();
String methodName = caller.getMethodName();
IllegalArgumentException exception = new IllegalArgumentException("State can not be equal to "+maximumEventForRemovingEvent + "method " + className + "." + methodName +", parameter maximumEventForRemovingEvent" );
throw sanitizeStackTrace(exception);
}
}
private void assertMainThread(String methodName) {
boolean isUiThread = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? Looper.getMainLooper().isCurrentThread() : Thread.currentThread() == Looper.getMainLooper().getThread();
if (!isUiThread) {throw new IllegalStateException("Cannot invoke " + methodName + " on a background"+ " thread"); }
}
private void assertNotNull(Object value, String paramName) {
if (value == null) {throwParameterIsNullException(paramName); } }
private void throwParameterIsNullException(String paramName) {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
StackTraceElement caller = stackTraceElements[3];
String className = caller.getClassName();
String methodName = caller.getMethodName();
IllegalArgumentException exception =
new IllegalArgumentException("Parameter specified as non-null is null: " +
"method " + className + "." + methodName +
", parameter " + paramName);
throw sanitizeStackTrace(exception);
}
private <T extends Throwable> T sanitizeStackTrace(T throwable) { return sanitizeStackTrace(throwable, this.getClass().getName());}
<T extends Throwable> T sanitizeStackTrace(T throwable, String classNameToDrop) {
StackTraceElement[] stackTrace = throwable.getStackTrace();
int size = stackTrace.length;
int lastIntrinsic = -1;
for (int i = 0; i < size; i++) {
if (classNameToDrop.equals(stackTrace[i].getClassName())) {lastIntrinsic = i; } }
StackTraceElement[] newStackTrace = Arrays.copyOfRange(stackTrace, lastIntrinsic + 1, size);
throwable.setStackTrace(newStackTrace);
return throwable;
}
}
答案 10 :(得分:1)
更简单的解决方案是使用EventLiveData lib:
implementation 'com.rugovit.eventlivedata:eventlivedata:1.0'
MutableEventLiveData<String> eventLiveData =new MutableEventLiveData<>();
viewModel.event.observe(this, Observer {
// ...
})
您可以像常规实时数据一样使用它。它是livedata的扩展,并支持livedata的所有功能。 与其他解决方案不同,它支持多个观察者。
答案 11 :(得分:0)
在调用android.arch.lifecycle.LiveData#observe
函数之前只需忽略数据。
class IgnoreHistoryLiveData<T> : MutableLiveData<T>() {
private val unactivedObservers = LinkedBlockingQueue<WrapperObserver<T>>()
override fun observe(owner: LifecycleOwner, observer: Observer<T>) {
val wo = WrapperObserver<T>(observer)
unactivedObservers.add(wo)
super.observe(owner, wo)
}
override fun setValue(value: T) {
while (unactivedObservers.isNotEmpty()) {
unactivedObservers.poll()?.actived = true
}
super.setValue(value)
}
}
private class WrapperObserver<T>(private val origin: Observer<T>) : Observer<T> {
var actived = false
override fun onChanged(t: T?) {
if (actived) {
origin.onChanged(t)
}
}
}