gal*_*irl 38 android observers android-room android-livedata
收到第一个结果后,如何删除观察者?下面是我尝试过的两种代码方式,但即使我已经删除了观察者,它们也都会继续接收更新.
Observer observer = new Observer<DownloadItem>() {
@Override
public void onChanged(@Nullable DownloadItem downloadItem) {
if(downloadItem!= null) {
DownloadManager.this.downloadManagerListener.onDownloadManagerFailed(null, "this item already exists");
return;
}
startDownload();
model.getDownloadByContentId(contentId).removeObservers((AppCompatActivity)context);
}
};
model.getDownloadByContentId(contentId).observeForever(observer);
Run Code Online (Sandbox Code Playgroud)
model.getDownloadByContentId(contentId).observe((AppCompatActivity)context, downloadItem-> {
if(downloadItem!= null) {
this.downloadManagerListener.onDownloadManagerFailed(null, "this item already exists");
return;
}
startDownload();
model.getDownloadByContentId(contentId).removeObserver(downloadItem-> {});
} );
Run Code Online (Sandbox Code Playgroud)
Com*_*are 26
你的第一个不会工作,因为observeForever()
没有任何关系LifecycleOwner
.
你的第二个将无法工作,因为你没有通过现有的注册观察员removeObserver()
.
首先需要解决您是否使用LiveData
了LifecycleOwner
(你的活动)或没有.我的假设是你应该使用a LifecycleOwner
.在这种情况下,使用:
Observer observer = new Observer<DownloadItem>() {
@Override
public void onChanged(@Nullable DownloadItem downloadItem) {
if(downloadItem!= null) {
DownloadManager.this.downloadManagerListener.onDownloadManagerFailed(null, "this item already exists");
return;
}
startDownload();
model.getDownloadByContentId(contentId).removeObservers((AppCompatActivity)context);
}
};
model.getDownloadByContentId(contentId).observe((AppCompatActivity)context, observer);
Run Code Online (Sandbox Code Playgroud)
Vin*_*nce 20
Kotlin有一个更方便的扩展解决方案:
fun <T> LiveData<T>.observeOnce(lifecycleOwner: LifecycleOwner, observer: Observer<T>) {
observe(lifecycleOwner, object : Observer<T> {
override fun onChanged(t: T?) {
observer.onChanged(t)
removeObserver(this)
}
})
}
Run Code Online (Sandbox Code Playgroud)
此扩展允许我们这样做:
liveData.observeOnce(this, Observer<Password> {
if (it != null) {
// do something
}
})
Run Code Online (Sandbox Code Playgroud)
因此,要回答您的原始问题,我们可以这样做:
val livedata = model.getDownloadByContentId(contentId)
livedata.observeOnce((AppCompatActivity) context, Observer<T> {
if (it != null) {
DownloadManager.this.downloadManagerListener.onDownloadManagerFailed(null, "this item already exists");
}
startDownload();
})
Run Code Online (Sandbox Code Playgroud)
原始来源在这里:https : //code.luasoftware.com/tutorials/android/android-livedata-observe-once-only-kotlin/
更新:@ Hakem-Zaied是正确的,我们需要使用observe
而不是observeForever
。
Ton*_*Joe 17
继CommonsWare回答之后removeObservers()
,您可以简单地调用removeObserver(this)
只删除此观察者,而不是调用哪个会删除附加到LiveData的所有观察者:
Observer observer = new Observer<DownloadItem>() {
@Override
public void onChanged(@Nullable DownloadItem downloadItem) {
if(downloadItem!= null) {
DownloadManager.this.downloadManagerListener.onDownloadManagerFailed(null, "this item already exists");
return;
}
startDownload();
model.getDownloadByContentId(contentId).removeObserver(this);
}
};
model.getDownloadByContentId(contentId).observe((AppCompatActivity)context, observer);
Run Code Online (Sandbox Code Playgroud)
注意: in removeObserver(this)
,this
指的是观察者实例,这仅适用于匿名内部类的情况.如果使用lambda,this
则将引用活动实例.
小智 10
observeOnce
许多用户已经建议使用Java 版本的方法。但在这里我们将在主代码中看到实现。
首先,我们需要创建Util类方法
public class LiveDataUtil {
public static <T> void observeOnce(final LiveData<T> liveData, final Observer<T> observer) {
liveData.observeForever(new Observer<T>() {
@Override
public void onChanged(T t) {
liveData.removeObserver(this);
observer.onChanged(t);
}
});
}}
Run Code Online (Sandbox Code Playgroud)
现在,我们需要在需要 ViewModel 的地方调用此类。
LiveDataUtil.observeOnce(viewModel.getUserDetails(), response-> {
if(response.isSuccessful()){
//Do your task
}
}
Run Code Online (Sandbox Code Playgroud)
就这样!
我同意上面的@vince,但我相信我们可以跳过传递lifecycleOwner
并按observerForever
以下方式使用:
fun <T> LiveData<T>.observeOnce(observer: Observer<T>) {
observeForever(object : Observer<T> {
override fun onChanged(t: T?) {
observer.onChanged(t)
removeObserver(this)
}
})
}
Run Code Online (Sandbox Code Playgroud)
或如下使用lifecycleOwner
with observe
:
fun <T> LiveData<T>.observeOnce(lifecycleOwner: LifecycleOwner, observer: Observer<T>) {
observe(lifecycleOwner, object : Observer<T> {
override fun onChanged(t: T?) {
observer.onChanged(t)
removeObserver(this)
}
})
}
Run Code Online (Sandbox Code Playgroud)
这是observeOnce
其他答案中建议的方法的 Java 版本(使用 util 类方法而不是 Kotlin 扩展函数):
public class LiveDataUtil {
public static <T> void observeOnce(final LiveData<T> liveData, final Observer<T> observer) {
liveData.observeForever(new Observer<T>() {
@Override
public void onChanged(T t) {
liveData.removeObserver(this);
observer.onChanged(t);
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
I love the generic solutions by @Vince and @Hakem Zaied, but to me the lambda version seems even better:
fun <T> LiveData<T>.observeOnce(observer: (T) -> Unit) {
observeForever(object: Observer<T> {
override fun onChanged(value: T) {
removeObserver(this)
observer(value)
}
})
}
fun <T> LiveData<T>.observeOnce(owner: LifecycleOwner, observer: (T) -> Unit) {
observe(owner, object: Observer<T> {
override fun onChanged(value: T) {
removeObserver(this)
observer(value)
}
})
}
Run Code Online (Sandbox Code Playgroud)
So you end up with:
val livedata = model.getDownloadByContentId(contentId)
livedata.observeOnce((AppCompatActivity) context) {
if (it != null) {
DownloadManager.this.downloadManagerListener.onDownloadManagerFailed(null, "this item already exists")
}
startDownload();
}
Run Code Online (Sandbox Code Playgroud)
Which I find cleaner.
Also, removeObserver()
is called first-thing as the observer is dispatched, which makes it safer (i.e. copes with potential runtime error throws from within the user's observer code).
小智 5
您正在多次创建实时数据实例 (model.getDownloadByContentId(contentId)),这就是这里的问题。
尝试这个:
LiveData myLiveData =model.getDownloadByContentId(contentId);
myLiveData.observe(getViewLifecycleOwner(), downloadItem-> {
if(downloadItem!= null) {
this.downloadManagerListener.onDownloadManagerFailed(null, "this item already exists");
return;
}
startDownload();
myLiveData.removeObservers(getViewLifecycleOwner());
} );
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
28109 次 |
最近记录: |