Android 房间数据库 ViewModel 不反映同步插入的数据
Android Room database ViewModel does not reflect synchronously inserted data
我遇到一个问题,即使我同步写入,写入我的 Room 数据库的数据也没有出现在 ViewModel 中。
这是日志的样子:
com.widget D/WriteActivity: Writing widget data to the database
com.widget D/WriteActivity: Starting the ReadActivity
com.widget D/ReadActivity: Got a new list of 0 objects
情况如下:
我有两个活动,WriteActivity
和 ReadActivity
。在 ReadActivity
内部,我有一个 ViewModel
侦听数据库更改(在 Activity 的 onCreate
方法中实例化):
// observe the widget data
WidgetViewModel widgetViewModel = ViewModelProviders.of(this).get(
WidgetViewModel.class);
widgetViewModel.getAllWidgets().observe(this, new Observer<List<Widget>>() {
@Override
public void onChanged(@Nullable final List<Widget> updatedWidgets) {
Log.d(TAG, "Got a new list of " + updatedWidgets.size() + " objects");
}
});
在 WriteActivity
内部,我有代码在后台线程上将对象添加到数据库,然后,一旦完成,它就会启动 ReadActivity
:
// persist the objects to the room database (doInBackground)
WidgetRepository myObjectRepository = new WidgetRepository(getApplication());
myObjectRepository.insert(myObjects); // myObjects is a list of 5 objects
// load the ReadActivity (onPostExecute)
Intent myIntent = new Intent(WriteActivity.this, ReadActivity.class);
WriteActivity.this.startActivity(myIntent);
这是我的 DAO:
@Dao
public interface WidgetDao {
@Query("SELECT * FROM widget_table")
LiveData<List<Widget>> getAll();
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Widget... widgets);
}
我的数据库:
@Database(entities = {Widget.class}, version = 1, exportSchema = false)
public abstract class WidgetDatabase extends RoomDatabase {
public abstract WidgetDao widgetDao();
private static volatile WidgetDatabase INSTANCE;
static WidgetDatabase getDatabase(final Context context) {
if (null == INSTANCE) {
synchronized (WidgetDatabase.class) {
if (null == INSTANCE) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
WidgetDatabase.class, "widget_database")
.build();
}
}
}
return INSTANCE;
}
}
我的存储库:
public class WidgetRepository {
private final WidgetDao widgetDao;
private final LiveData<List<Widget>> widgets;
public WidgetRepository(Application application) {
WidgetDatabase db = WidgetDatabase.getDatabase(application);
widgetDao = db.widgetDao();
widgets = widgetDao.getAll();
}
public LiveData<List<Widget>> getWidgets() {
return widgets;
}
public void insert(List<Widget> widgetsToInsert) {
widgetDao.insert(widgetsToInsert.toArray(
new Widget[widgetsToInsert.size()]));
}
我的视图模型:
public class WidgetViewModel extends AndroidViewModel {
private final LiveData<List<Widget>> widgets;
public WidgetViewModel (Application application) {
super(application);
WidgetRepository widgetRepository = new WidgetRepository(application);
widgets = widgetRepository.getWidgets();
}
public LiveData<List<Widget>> getAllWidgets() { return widgets;
}
}
您的问题是 LiveData<List<Widget>>
没有收到通知。
那么,如何更新呢?
见下文,
Update LiveData objects
LiveData
has no publicly available methods to update the stored data.
The MutableLiveData
class exposes the setValue(T)
and postValue(T)
methods publicly and you must use these if you need to edit the value
stored in a LiveData
object. Usually MutableLiveData
is used in the
ViewModel and then the ViewModel only exposes immutable LiveData
objects to the observers.
因此,您可以对 ViewModel
进行更改:
public class WidgetViewModel extends AndroidViewModel {
private final MutableLiveData<List<Widget>> widgets = new MutableLiveData<List<Widget>>(); // Make it mutable livedata
public WidgetViewModel (Application application) {
super(application);
WidgetRepository widgetRepository = new WidgetRepository(application);
//widgets = widgetRepository.getWidgets();
//use this to update your live data instead,
widgets.setValue(widgetRepository.getWidgets().getValue()); // This will update your live data, use like this for future updates.
}
public LiveData<List<Widget>> getAllWidgets() { return widgets;
}
}
从 here
查看更多
我明白发生了什么事。这很尴尬……当我问我的问题时,我对 LiveData 的工作原理有一个根本性的误解。 RTFM 天哪 :)
阅读文档后,我得到了一个惊人的启示:LiveData 与 activity 的生命周期相关联。在我给出的示例中,我试图在 ReadActivity
的 onResume
期间访问 ViewModel,因为我想确保 UI 正确更新。新手错误。像个傻瓜一样,我相信 Observer 回调只会在 LiveData 封装的数据被修改时触发。实际上,无论数据是否发生变化,当 activity 激活时都会调用 Observer 中的 LiveData 回调,因此无需尝试在 onResume
生命周期方法中手动执行任何操作。等待Observer的onChanged
回调,到时候更新UI即可。
应用程序现在运行良好,感谢所有阅读我的问题的人。
我遇到一个问题,即使我同步写入,写入我的 Room 数据库的数据也没有出现在 ViewModel 中。
这是日志的样子:
com.widget D/WriteActivity: Writing widget data to the database
com.widget D/WriteActivity: Starting the ReadActivity
com.widget D/ReadActivity: Got a new list of 0 objects
情况如下:
我有两个活动,WriteActivity
和 ReadActivity
。在 ReadActivity
内部,我有一个 ViewModel
侦听数据库更改(在 Activity 的 onCreate
方法中实例化):
// observe the widget data
WidgetViewModel widgetViewModel = ViewModelProviders.of(this).get(
WidgetViewModel.class);
widgetViewModel.getAllWidgets().observe(this, new Observer<List<Widget>>() {
@Override
public void onChanged(@Nullable final List<Widget> updatedWidgets) {
Log.d(TAG, "Got a new list of " + updatedWidgets.size() + " objects");
}
});
在 WriteActivity
内部,我有代码在后台线程上将对象添加到数据库,然后,一旦完成,它就会启动 ReadActivity
:
// persist the objects to the room database (doInBackground)
WidgetRepository myObjectRepository = new WidgetRepository(getApplication());
myObjectRepository.insert(myObjects); // myObjects is a list of 5 objects
// load the ReadActivity (onPostExecute)
Intent myIntent = new Intent(WriteActivity.this, ReadActivity.class);
WriteActivity.this.startActivity(myIntent);
这是我的 DAO:
@Dao
public interface WidgetDao {
@Query("SELECT * FROM widget_table")
LiveData<List<Widget>> getAll();
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Widget... widgets);
}
我的数据库:
@Database(entities = {Widget.class}, version = 1, exportSchema = false)
public abstract class WidgetDatabase extends RoomDatabase {
public abstract WidgetDao widgetDao();
private static volatile WidgetDatabase INSTANCE;
static WidgetDatabase getDatabase(final Context context) {
if (null == INSTANCE) {
synchronized (WidgetDatabase.class) {
if (null == INSTANCE) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
WidgetDatabase.class, "widget_database")
.build();
}
}
}
return INSTANCE;
}
}
我的存储库:
public class WidgetRepository {
private final WidgetDao widgetDao;
private final LiveData<List<Widget>> widgets;
public WidgetRepository(Application application) {
WidgetDatabase db = WidgetDatabase.getDatabase(application);
widgetDao = db.widgetDao();
widgets = widgetDao.getAll();
}
public LiveData<List<Widget>> getWidgets() {
return widgets;
}
public void insert(List<Widget> widgetsToInsert) {
widgetDao.insert(widgetsToInsert.toArray(
new Widget[widgetsToInsert.size()]));
}
我的视图模型:
public class WidgetViewModel extends AndroidViewModel {
private final LiveData<List<Widget>> widgets;
public WidgetViewModel (Application application) {
super(application);
WidgetRepository widgetRepository = new WidgetRepository(application);
widgets = widgetRepository.getWidgets();
}
public LiveData<List<Widget>> getAllWidgets() { return widgets;
}
}
您的问题是 LiveData<List<Widget>>
没有收到通知。
那么,如何更新呢?
见下文,
Update LiveData objects
LiveData
has no publicly available methods to update the stored data. TheMutableLiveData
class exposes thesetValue(T)
andpostValue(T)
methods publicly and you must use these if you need to edit the value stored in aLiveData
object. UsuallyMutableLiveData
is used in the ViewModel and then the ViewModel only exposes immutable LiveData objects to the observers.
因此,您可以对 ViewModel
进行更改:
public class WidgetViewModel extends AndroidViewModel {
private final MutableLiveData<List<Widget>> widgets = new MutableLiveData<List<Widget>>(); // Make it mutable livedata
public WidgetViewModel (Application application) {
super(application);
WidgetRepository widgetRepository = new WidgetRepository(application);
//widgets = widgetRepository.getWidgets();
//use this to update your live data instead,
widgets.setValue(widgetRepository.getWidgets().getValue()); // This will update your live data, use like this for future updates.
}
public LiveData<List<Widget>> getAllWidgets() { return widgets;
}
}
从 here
查看更多我明白发生了什么事。这很尴尬……当我问我的问题时,我对 LiveData 的工作原理有一个根本性的误解。 RTFM 天哪 :)
阅读文档后,我得到了一个惊人的启示:LiveData 与 activity 的生命周期相关联。在我给出的示例中,我试图在 ReadActivity
的 onResume
期间访问 ViewModel,因为我想确保 UI 正确更新。新手错误。像个傻瓜一样,我相信 Observer 回调只会在 LiveData 封装的数据被修改时触发。实际上,无论数据是否发生变化,当 activity 激活时都会调用 Observer 中的 LiveData 回调,因此无需尝试在 onResume
生命周期方法中手动执行任何操作。等待Observer的onChanged
回调,到时候更新UI即可。
应用程序现在运行良好,感谢所有阅读我的问题的人。