Android 在使用MVVM模型观察数据库更改的活动中返回LiveData时出现问题
在我的应用程序中,我从存储库中的Room数据库(SQLite)返回LiveData,并观察应用程序活动中的数据 问题是:在活动中使用LiveData,使用MVVM模型观察数据库中的更改,并在数据更改时运行一些代码(因为观察就是这样工作的) 存储库中的方法如下所示:Android 在使用MVVM模型观察数据库更改的活动中返回LiveData时出现问题,android,mvvm,android-room,android-livedata,Android,Mvvm,Android Room,Android Livedata,在我的应用程序中,我从存储库中的Room数据库(SQLite)返回LiveData,并观察应用程序活动中的数据 问题是:在活动中使用LiveData,使用MVVM模型观察数据库中的更改,并在数据更改时运行一些代码(因为观察就是这样工作的) 存储库中的方法如下所示: public LiveData<TourWithAllGeoPoints> getTourWithAllGeoPoints(long tourId, boolean mIsFirstTime) { if (!mIs
public LiveData<TourWithAllGeoPoints> getTourWithAllGeoPoints(long tourId, boolean mIsFirstTime) {
if (!mIsFirstTime) {
return tourWithAllGeoPoints;
}
MyTourAssistentDatabase.databaseWriteExecutor.execute(()-> {
tourWithAllGeoPoints = toursDAO.getTourWithAllGeoPoints(tourId); //this part finishes after reuturn
});
return tourWithAllGeoPoints; //this part returns
}
但问题是,在execute()部分完成之前,该方法返回“tourWithAllGeoPoints”。这意味着它返回一个空的LiveData。或者我们在MainActivity上观察到的LiveData与我们从toursDAO获得的LiveData不同
因此,在活动中,它观察空的LiveData
我尝试的解决方案是:
1)我可以像这样在主线程中运行查询:
public LiveData<TourWithAllGeoPoints> getTourWithAllGeoPoints(long tourId, boolean mIsFirstTime) {
if (!mIsFirstTime) {
return tourWithAllGeoPoints;
}
tourWithAllGeoPoints = toursDAO.getTourWithAllGeoPoints(tourId);
return tourWithAllGeoPoints;
}
public LiveData<TourWithAllGeoPoints> getTourWithAllGeoPoints(long tourId, boolean mIsFirstTime) {
if (!mIsFirstTime) {
return tourWithAllGeoPoints;
}
MyTourAssistentDatabase.databaseWriteExecutor.execute(()-> {
TourWithAllGeoPoints twagp = toursDAO.getTourWithAllGeoPoints(tourId);
tourWithAllGeoPoints.postValue(twagp)
});
return tourWithAllGeoPoints;
}
public LiveData<LiveData<TourWithAllGeoPoints>> getTourWithAllGeoPoints(long tourId, boolean mIsFirstTime) {
if (!mIsFirstTime) {
return tourWithAllGeoPoints;
}
MyTourAssistentDatabase.databaseWriteExecutor.execute(()-> {
LiveData<TourWithAllGeoPoints> twagp = toursDAO.getTourWithAllGeoPoints(tourId); //returns LiveData
tourWithAllGeoPoints.postValue(twagp)
});
return tourWithAllGeoPoints;
}
public LiveData getTourWithAllGeoPoints(长巡演,布尔错误优先时间){
如果(!mIsFirstTime){
返回所有地理点的旅游;
}
tourWithAllGeoPoints=toursDAO.getTourWithAllGeoPoints(tourId);
返回所有地理点的旅游;
}
但随后它会发出警告消息,提示不要在主线程上运行对Room数据库的查询,因为这可能需要很长时间
2)或者我可以让toursDAO.getTourWithAllGeoPoints(tourId)返回TourWithAllGeoPoints对象而不是LiveData,并将其放入LiveDataobject,如下所示:
public LiveData<TourWithAllGeoPoints> getTourWithAllGeoPoints(long tourId, boolean mIsFirstTime) {
if (!mIsFirstTime) {
return tourWithAllGeoPoints;
}
tourWithAllGeoPoints = toursDAO.getTourWithAllGeoPoints(tourId);
return tourWithAllGeoPoints;
}
public LiveData<TourWithAllGeoPoints> getTourWithAllGeoPoints(long tourId, boolean mIsFirstTime) {
if (!mIsFirstTime) {
return tourWithAllGeoPoints;
}
MyTourAssistentDatabase.databaseWriteExecutor.execute(()-> {
TourWithAllGeoPoints twagp = toursDAO.getTourWithAllGeoPoints(tourId);
tourWithAllGeoPoints.postValue(twagp)
});
return tourWithAllGeoPoints;
}
public LiveData<LiveData<TourWithAllGeoPoints>> getTourWithAllGeoPoints(long tourId, boolean mIsFirstTime) {
if (!mIsFirstTime) {
return tourWithAllGeoPoints;
}
MyTourAssistentDatabase.databaseWriteExecutor.execute(()-> {
LiveData<TourWithAllGeoPoints> twagp = toursDAO.getTourWithAllGeoPoints(tourId); //returns LiveData
tourWithAllGeoPoints.postValue(twagp)
});
return tourWithAllGeoPoints;
}
public LiveData getTourWithAllGeoPoints(长巡演,布尔错误优先时间){
如果(!mIsFirstTime){
返回所有地理点的旅游;
}
MyTourAssistentDatabase.databaseWriteExecutor.execute(()->{
TourWithAllGeoPoints twagp=toursDAO.getTourWithAllGeoPoints(tourId);
tourWithAllGeoPoints.postValue(twagp)
});
返回所有地理点的旅游;
}
这样它就能观察到LiveData中的变化。但我无法观察数据库中所做的更改,因为它只返回一个列表。这意味着每次在数据库中进行更改时都必须运行相同的方法
3)或者我可以将LiveData放在LiveData中,也可以这样:
public LiveData<TourWithAllGeoPoints> getTourWithAllGeoPoints(long tourId, boolean mIsFirstTime) {
if (!mIsFirstTime) {
return tourWithAllGeoPoints;
}
tourWithAllGeoPoints = toursDAO.getTourWithAllGeoPoints(tourId);
return tourWithAllGeoPoints;
}
public LiveData<TourWithAllGeoPoints> getTourWithAllGeoPoints(long tourId, boolean mIsFirstTime) {
if (!mIsFirstTime) {
return tourWithAllGeoPoints;
}
MyTourAssistentDatabase.databaseWriteExecutor.execute(()-> {
TourWithAllGeoPoints twagp = toursDAO.getTourWithAllGeoPoints(tourId);
tourWithAllGeoPoints.postValue(twagp)
});
return tourWithAllGeoPoints;
}
public LiveData<LiveData<TourWithAllGeoPoints>> getTourWithAllGeoPoints(long tourId, boolean mIsFirstTime) {
if (!mIsFirstTime) {
return tourWithAllGeoPoints;
}
MyTourAssistentDatabase.databaseWriteExecutor.execute(()-> {
LiveData<TourWithAllGeoPoints> twagp = toursDAO.getTourWithAllGeoPoints(tourId); //returns LiveData
tourWithAllGeoPoints.postValue(twagp)
});
return tourWithAllGeoPoints;
}
public LiveData getTourWithAllGeoPoints(长巡演,布尔错误优先时间){
如果(!mIsFirstTime){
返回所有地理点的旅游;
}
MyTourAssistentDatabase.databaseWriteExecutor.execute(()->{
LiveData twagp=toursDAO.getTourWithAllGeoPoints(tourId);//返回LiveData
tourWithAllGeoPoints.postValue(twagp)
});
返回所有地理点的旅游;
}
但我不知道将LiveData放在LiveData中是否是个好主意
或其他解决方案。但我如何解决这个问题?
问题是:在活动中使用LiveData,使用MVVM模型观察数据库中的更改,并在数据更改时运行一些代码(因为这就是观察的工作方式)。对于您描述的特定问题(即返回第一个
TourWithAllGeoPoints
而不返回任何其他内容),似乎LiveData
不是您在这里可以使用的最合适的数据类型LiveData
用于以下情况:正如其名称所示,基础数据是活动的,并且随时可能更改,并且每次更改时都需要观察数据。如果您只需要一个值,那么最好不要使用LiveData
。只需将DAO方法getTourWithAllGeoPoints
返回TourWithAllGeoPoints
(不带LiveData
),并从后台线程调用即可。请看一些方法来做到这一点。在这种情况下,使用Kotlin协程要容易得多,但您需要使用Kotlin(我推荐:)
但是,如果您描述的问题是一般性的(不仅仅是一次返回一个值),那么您可以使用MediatorLiveData
来观察LiveData
,并在每次发出新值时发布不同的(或不是)内容。请看下面的代码:
private MediatorLiveData<TourWithAllGeoPoints> mediator;
public YourRepositoryConstructor() {
mediator = new MediatorLiveData<>();
mediator.addSource(toursDAO.getTourWithAllGeoPoints(tourId), data -> {
if (mediator.getValue() != null) {
mediator.setValue(data);
}
});
return mediator;
}
public LiveData<TourWithAllGeoPoints> getTourWithAllGeoPoints(long tourId, boolean mIsFirstTime) {
return mediator;
}
私有中介livedata中介;
公共YourRepositoryConstructor(){
mediator=new MediatorLiveData();
mediator.addSource(toursDAO.getTourWithAllGeoPoints(tourId),数据->{
if(mediator.getValue()!=null){
mediator.setValue(数据);
}
});
回归调解人;
}
public LiveData getTourWithAllGeoPoints(长巡演,布尔错误优先时间){
回归调解人;
}
MediatorLiveData
观察一个(或多个)其他LiveData
对象,并根据其他LiveData
对象的更改发出新值。它可能会发出不同的数据类型(即,它不必是底层LiveData
对象的同一类型),甚至根本不会发出任何东西。这一切都取决于您的livedata
代码。具体来说,在本例中,每次getTourWithAllGeoPoints
的结果发出新的内容时,您MediatorLiveData
将对此作出反应,并且仅在第一次发出新的值时才发出。通过检查其值是否为null
,它不需要变量mIsFirstTime
(除非null
在这种情况下是有效值)
MediatorLiveData
是一种更通用的方法,适用于您所描述的场景类型,但是如果您只需要查询一个结果,那么可能需要付出太多的努力,而您可能根本不使用LiveData
来解决这个问题