#android #android-room #android-viewmodel
#Android #android-комната #android-viewmodel
Вопрос:
Я следил за этой комнатой с помощью руководства по просмотру, и все работает так, как ожидалось. Теперь я пытаюсь реализовать @rawQuery и отобразить живые данные с помощью ViewModel. Я хочу отобразить список элементов, которые имеют определенное значение столбца (в данном случае строку). В этой документации этот код, похоже, является решением для моей желаемой функции приложения:
@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"));
Я хочу, чтобы мой запрос на чтение создавался во время выполнения, когда значение NameColumn передается в simpleSQLiteQuery(String nameColumn)
функцию, которая возвращает new SimpleSQLiteQuery
.
Вот мой код:
Dao
@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;
}
ViewModel
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 также указывает строки A и B в ShotDao_Impl.java сгенерированный исходный файл.
@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 _resu<
} finally {
_cursor.close();
}
}
}.getLiveData();
}
Ответ №1:
Эта строка в viewmodel выдает ошибку. Вы устанавливаете mSimpleSQLiteQuery
для room db значение null.
mNameColumn = mRepository.getNameColumn(mSimpleSQLiteQuery);
Вы должны удалить строку выше из viewmodel и изменить getNameColumn()
функцию следующим образом:
public LiveData<List<Shot>> getNameColumn (SimpleSQLiteQuery simpleSQLiteQuery) {
return mRepository.getNameColumn(mSimpleSQLiteQuery);;
}
Редактировать:
Вы можете упростить свой код, изменив свой DAO. Вы можете передавать параметры прямо в DAO.
Например.
@Query("SELECT * FROM shots WHERE nameColumn = :columnName")
LiveData<List<Shot>> getNameColumn(String columnName);
с помощью этой функции вы можете извлекать данные shots
в соответствии с именем столбца
Комментарии:
1. Спасибо за решение и пример упрощения!
Ответ №2:
mNameColumn
Живые данные в ViewModel создаются с помощью null
mSimpleSQLiteQuery
во время выполнения конструктора ViewModel. Вы устанавливаете это в getNameColumn
, но обратите внимание, что ваши livedata не знают об этом новом значении.
Следовательно, impl ShotDao
for LiveData<List<Shot>> getNameColumn(SupportSQLiteQuery supportSQLiteQuery);
получает null
SupportSQLiteQuery, что приводит к сбою.