如何在收到第一个结果后移除观察者?下面是我尝试过的两种代码方式,但它们都不断接收更新,即使我已经删除了观察者。
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);
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-> {});
} );
对于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)
}
})
}
这次延期使我们能够这样做:
liveData.observeOnce(this, Observer<Password> {
if (it != null) {
// do something
}
})
为了回答你原来的问题,我们可以这样做:
val livedata = model.getDownloadByContentId(contentId)
livedata.observeOnce((AppCompatActivity) context, Observer<T> {
if (it != null) {
DownloadManager.this.downloadManagerListener.onDownloadManagerFailed(null, "this item already exists");
}
startDownload();
})
原始源代码在这里:https://code.luasoftware.com/tutorials/android/android-livedata-observe-once-only-kotlin/
更新:@hakem-zaied是对的,我们需要使用observe
而不是observeForever
。
您的第一个将不起作用,因为observeForever()
没有绑定到任何LifecyCleOwner
。
您的第二个将不起作用,因为您没有将现有的已注册观察者传递给removeobserver()
。
您首先需要确定是否将LiveData
与LifecycleOwner
(您的activity)一起使用。我的假设是,您应该使用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);
我想在片段中加载任务,在片段的onviewCreate中,我注册observer,在片段的onResume中,我异步加载任务,当第一次输入片段时,它工作正常,但当我导航到其他片段,然后返回到任务片段时,回调将被调用两次。 我知道如果LiveData已经有了数据集,它将被传递给观察者,因此当返回到任务片段时,在中注册观察者时,将触发,在onResume中,将第二次触发,我想知道如何避免这种情况。我搜
在我正在工作的一个项目中,我使用了paginglibrary和Reverfit。这是我第一次这么做。 数据正常返回。但是我注意到我的viewmodel(更确切地说是我的LiveData)中的观察者在我的PageKeyedDataSource中的LoadIsitial回调之前被调用。这将使传递给适配器的列表为空。为什么在我回调之前调用Observer?
我有一个片段和一个相应的viewmodel类。我在Fragment方法上从DB获取包装为LiveData的联系人列表。它工作得很好,我使用PagedListAdapter显示联系人列表,如下所示: 我在我的片段中添加了一个观察者,如下所示: 有一个按钮在我的片段,它把我带到另一个屏幕,在那个屏幕上我添加更多的联系人到表。但当我从那个屏幕回到我的片段时,观察者并没有被调用。这意味着返回时不会调用方法
此外,为什么Viewmodel不能观察到它自己的LiveData的变化?
我有一个单独的类来处理数据提取(特别是Firebase),我通常从它返回LiveData对象并异步更新它们。现在我希望将返回的数据存储在ViewModel中,但问题是为了获得所述值,我需要观察从数据提取类返回的LiveData对象。observe方法需要一个LifecycleOwner对象作为第一个参数,但我的ViewModel中显然没有这个对象,而且我知道我不应该在ViewModel中保留对ac