android - @RawQuery 与 ViewModel
问题描述
我遵循了这个带视图的房间教程,一切都按预期工作。现在我正在尝试实现@RawQuery 并使用 ViewModel 显示 LiveData。我想显示具有特定列值的项目列表(在本例中为字符串)。在本文档中,此代码似乎是我想要的应用程序功能的解决方案:
@Dao
interface RawDao {
@RawQuery(observedEntities = User.class)
LiveData<List<User>> getUsers(SupportSQLiteQuery query);
}
LiveData<List<User>> liveUsers = rawDao.getUsers(
new SimpleSQLiteQuery("SELECT * FROM User ORDER BY name DESC"));
simpleSQLiteQuery(String nameColumn)
我希望在将 nameColumn 值传递给返回的函数时在运行时构造我的读取查询new SimpleSQLiteQuery
。
这是我的代码:
道
@Dao
public interface ShotDao {
@RawQuery(observedEntities = Shot.class)
LiveData<List<Shot>> getNameColumn(SupportSQLiteQuery supportSQLiteQuery);
}
存储库
private ShotDao mShotDao;
private LiveData<List<Shot>> mNameColumn;
private SimpleSQLiteQuery mSimpleSQLiteQuery;
public ShotRepository(Application application) {
WrappShotDatabase database = WrappShotDatabase.getDatabase(application);
mShotDao = database.shotDao();
mNameColumn = mShotDao.getNameColumn(mSimpleSQLiteQuery);
}
public LiveData<List<Shot>> getNameColumn (SimpleSQLiteQuery simpleSQLiteQuery) {
this.mSimpleSQLiteQuery = simpleSQLiteQuery;
return mNameColumn;
}
视图模型
private ShotRepository mRepository;
private LiveData<List<Shot>> mNameColumn;
private SimpleSQLiteQuery mSimpleSQLiteQuery;
public ShotViewModel(Application application) {
super(application);
mRepository = new ShotRepository(application);
mNameColumn = mRepository.getNameColumn(mSimpleSQLiteQuery);
}
public LiveData<List<Shot>> getNameColumn (SimpleSQLiteQuery simpleSQLiteQuery) {
this.mSimpleSQLiteQuery = simpleSQLiteQuery;
return mNameColumn;
}
活动
String columnName = mColumnName;
shotViewModel = ViewModelProviders.of(this).get(ShotViewModel.class);
shotViewModel.getNameColumn(simpleSQLiteQuery(columnName)).observe(this, new Observer<List<Shot>>() {
@Override
public void onChanged(@Nullable List<Shot> shots) {
mShotAdapter.submitList(shots);
}
});
SimpleSQLiteQuery 方法
private SimpleSQLiteQuery simpleSQLiteQuery(String nameColumn) {
String select = "SELECT * FROM ";
String tableName = "shots";
String where = " WHERE nameColumn=\"";
String close = "\"";
return new SimpleSQLiteQuery(select + tableName + where + nameColumn + close);
}
创建 Activity 时,我的应用程序崩溃并出现错误:
java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.String android.arch.persistence.db.SupportSQLiteQuery.getSql()' on a null object reference
我不明白为什么我的对象没有被创建,什么时候应该创建。Logcat 还指出了 ShotDao_Impl.java 生成的源文件中的 A 行和 B 行。
@Override
public LiveData<List<Shot>> getNameColumn(SupportSQLiteQuery supportSQLiteQuery) {
final SupportSQLiteQuery _internalQuery = supportSQLiteQuery;
return new ComputableLiveData<List<Shot>>() { // row A
private Observer _observer;
@Override
protected List<Shot> compute() {
if (_observer == null) {
_observer = new Observer("shots") {
@Override
public void onInvalidated(@NonNull Set<String> tables) {
invalidate();
}
};
__db.getInvalidationTracker().addWeakObserver(_observer);
}
final Cursor _cursor = __db.query(_internalQuery); // row B
try {
final List<Shot> _result = new ArrayList<Shot>(_cursor.getCount());
while(_cursor.moveToNext()) {
final Shot _item;
_item = __entityCursorConverter_comExampleAndroidWrappDatabaseShot(_cursor);
_result.add(_item);
}
return _result;
} finally {
_cursor.close();
}
}
}.getLiveData();
}
解决方案
ViewModel 中的mNameColumn
LiveData 是在null
mSimpleSQLiteQuery
ViewModel 构造函数执行时创建的。您正在设置它,getNameColumn
但请注意您的 livedata 不知道这个新值。
ShotDao
因此for的 implLiveData<List<Shot>> getNameColumn(SupportSQLiteQuery supportSQLiteQuery);
接收null
SupportSQLiteQuery 导致崩溃。