LiveData.getValue() returns 空房间
LiveData.getValue() returns null with Room
Java POJO 对象
public class Section {
@ColumnInfo(name="section_id")
public int mSectionId;
@ColumnInfo(name="section_name")
public String mSectionName;
public int getSectionId() {
return mSectionId;
}
public void setSectionId(int mSectionId) {
this.mSectionId = mSectionId;
}
public String getSectionName() {
return mSectionName;
}
public void setSectionName(String mSectionName) {
this.mSectionName = mSectionName;
}
}
我的查询方法
@Query("SELECT * FROM section")
LiveData<List<Section>> getAllSections();
正在访问数据库
final LiveData<List<Section>> sections = mDb.sectionDAO().getAllSections();
在下一行我正在检查 sections.getValue()
,尽管我在数据库中有数据,但它总是给我 null,后来我在 onChanged()
方法中获取值。
sections.observe(this, new Observer<List<Section>>() {
@Override
public void onChanged(@Nullable List<Section> sections){
}
});
但是当我从查询中省略 LiveData 时,我得到了预期的数据。
查询方式:
@Query("SELECT * FROM section")
List<Section> getAllSections();
正在访问数据库:
final List<Section> sections = mDb.sectionDAO().getAllSections();
if sections.getValue() is null I have to call api for data and insert
in into the database
您可以使用 onChange
方法处理此问题:
sections.observe(this, new Observer<List<Section>>() {
@Override
public void onChanged(@Nullable List<Section> sections){
if(sections == null || sections.size() == 0) {
// No data in your database, call your api for data
} else {
// One or more items retrieved, no need to call your api for data.
}
}
});
但是您最好将此 Database/Table 初始化逻辑放到存储库 class 中。查看 Google's sample. See DatabaseCreator class.
我通过这个方法解决了这个问题
private MediatorLiveData<List<Section>> mSectionLive = new MediatorLiveData<>();
.
.
.
@Override
public LiveData<List<Section>> getAllSections() {
final LiveData<List<Section>> sections = mDb.sectionDAO().getAllSections();
mSectionLive.addSource(sections, new Observer<List<Section>>() {
@Override
public void onChanged(@Nullable List<Section> sectionList) {
if(sectionList == null || sectionList.isEmpty()) {
// Fetch data from API
}else{
mSectionLive.removeSource(sections);
mSectionLive.setValue(sectionList);
}
}
});
return mSectionLive;
}
我解决了类似的问题如下
在您的 ViewModel 中 class
private LiveData<List<Section>> mSections;
@Override
public LiveData<List<Section>> getAllSections() {
if (mSections == null) {
mSections = mDb.sectionDAO().getAllSections();
}
return mSections;
}
这都是必需的。切勿更改 LiveData 的实例。
On the next line I am checking sections.getValue() which is always giving me null although I have data in the DataBase and later I am getting the value in the onChanged() method.
这是正常行为,因为 return LiveData 的查询正在异步工作。那一刻该值为空。
所以调用这个方法
LiveData<List<Section>> getAllSections();
稍后你会在这里得到结果
sections.observe(this, new Observer<List<Section>>() {
@Override
public void onChanged(@Nullable List<Section> sections){
}
});
来自文档:
Room does not allow accessing the database on the main thread unless you called allowMainThreadQueries() on the builder because it might potentially lock the UI for a long periods of time. Asynchronous queries (queries that return LiveData or RxJava Flowable) are exempt from this rule since they asynchronously run the query on a background thread when needed.
LiveData 是一个异步查询,你得到了 LiveData 对象,但它可能不包含任何数据。您可以使用额外的方法来等待数据被填充然后提取数据。
public static <T> T getValue(LiveData<T> liveData) throws InterruptedException {
final Object[] objects = new Object[1];
final CountDownLatch latch = new CountDownLatch(1);
Observer observer = new Observer() {
@Override
public void onChanged(@Nullable Object o) {
objects[0] = o;
latch.countDown();
liveData.removeObserver(this);
}
};
liveData.observeForever(observer);
latch.await(2, TimeUnit.SECONDS);
return (T) objects[0];
}
如果您需要在代码中从数据库中同步获取数据,我建议创建另一个没有 LiveData 的查询。
DAO:
@Query("SELECT COUNT(*) FROM section")
int countAllSections();
视图模型:
Integer countAllSections() {
return new CountAllSectionsTask().execute().get();
}
private static class CountAllSectionsTask extends AsyncTask<Void, Void, Integer> {
@Override
protected Integer doInBackground(Void... notes) {
return mDb.sectionDAO().countAllSections();
}
}
对于遇到此问题的任何人。如果您正在调用 LiveData.getValue() 并且您始终得到 null。您可能忘记调用 LiveData.observe()。如果您忘记这样做,getValue() 将始终 return null 特别是对于 List<> 数据类型。
Java POJO 对象
public class Section {
@ColumnInfo(name="section_id")
public int mSectionId;
@ColumnInfo(name="section_name")
public String mSectionName;
public int getSectionId() {
return mSectionId;
}
public void setSectionId(int mSectionId) {
this.mSectionId = mSectionId;
}
public String getSectionName() {
return mSectionName;
}
public void setSectionName(String mSectionName) {
this.mSectionName = mSectionName;
}
}
我的查询方法
@Query("SELECT * FROM section")
LiveData<List<Section>> getAllSections();
正在访问数据库
final LiveData<List<Section>> sections = mDb.sectionDAO().getAllSections();
在下一行我正在检查 sections.getValue()
,尽管我在数据库中有数据,但它总是给我 null,后来我在 onChanged()
方法中获取值。
sections.observe(this, new Observer<List<Section>>() {
@Override
public void onChanged(@Nullable List<Section> sections){
}
});
但是当我从查询中省略 LiveData 时,我得到了预期的数据。 查询方式:
@Query("SELECT * FROM section")
List<Section> getAllSections();
正在访问数据库:
final List<Section> sections = mDb.sectionDAO().getAllSections();
if sections.getValue() is null I have to call api for data and insert in into the database
您可以使用 onChange
方法处理此问题:
sections.observe(this, new Observer<List<Section>>() {
@Override
public void onChanged(@Nullable List<Section> sections){
if(sections == null || sections.size() == 0) {
// No data in your database, call your api for data
} else {
// One or more items retrieved, no need to call your api for data.
}
}
});
但是您最好将此 Database/Table 初始化逻辑放到存储库 class 中。查看 Google's sample. See DatabaseCreator class.
我通过这个方法解决了这个问题
private MediatorLiveData<List<Section>> mSectionLive = new MediatorLiveData<>();
.
.
.
@Override
public LiveData<List<Section>> getAllSections() {
final LiveData<List<Section>> sections = mDb.sectionDAO().getAllSections();
mSectionLive.addSource(sections, new Observer<List<Section>>() {
@Override
public void onChanged(@Nullable List<Section> sectionList) {
if(sectionList == null || sectionList.isEmpty()) {
// Fetch data from API
}else{
mSectionLive.removeSource(sections);
mSectionLive.setValue(sectionList);
}
}
});
return mSectionLive;
}
我解决了类似的问题如下
在您的 ViewModel 中 class
private LiveData<List<Section>> mSections;
@Override
public LiveData<List<Section>> getAllSections() {
if (mSections == null) {
mSections = mDb.sectionDAO().getAllSections();
}
return mSections;
}
这都是必需的。切勿更改 LiveData 的实例。
On the next line I am checking sections.getValue() which is always giving me null although I have data in the DataBase and later I am getting the value in the onChanged() method.
这是正常行为,因为 return LiveData 的查询正在异步工作。那一刻该值为空。
所以调用这个方法
LiveData<List<Section>> getAllSections();
稍后你会在这里得到结果
sections.observe(this, new Observer<List<Section>>() {
@Override
public void onChanged(@Nullable List<Section> sections){
}
});
来自文档:
Room does not allow accessing the database on the main thread unless you called allowMainThreadQueries() on the builder because it might potentially lock the UI for a long periods of time. Asynchronous queries (queries that return LiveData or RxJava Flowable) are exempt from this rule since they asynchronously run the query on a background thread when needed.
LiveData 是一个异步查询,你得到了 LiveData 对象,但它可能不包含任何数据。您可以使用额外的方法来等待数据被填充然后提取数据。
public static <T> T getValue(LiveData<T> liveData) throws InterruptedException {
final Object[] objects = new Object[1];
final CountDownLatch latch = new CountDownLatch(1);
Observer observer = new Observer() {
@Override
public void onChanged(@Nullable Object o) {
objects[0] = o;
latch.countDown();
liveData.removeObserver(this);
}
};
liveData.observeForever(observer);
latch.await(2, TimeUnit.SECONDS);
return (T) objects[0];
}
如果您需要在代码中从数据库中同步获取数据,我建议创建另一个没有 LiveData 的查询。
DAO:
@Query("SELECT COUNT(*) FROM section")
int countAllSections();
视图模型:
Integer countAllSections() {
return new CountAllSectionsTask().execute().get();
}
private static class CountAllSectionsTask extends AsyncTask<Void, Void, Integer> {
@Override
protected Integer doInBackground(Void... notes) {
return mDb.sectionDAO().countAllSections();
}
}
对于遇到此问题的任何人。如果您正在调用 LiveData.getValue() 并且您始终得到 null。您可能忘记调用 LiveData.observe()。如果您忘记这样做,getValue() 将始终 return null 特别是对于 List<> 数据类型。