У меня есть LiveData
для книг в конструкторе ViewModel
:
LiveData<List<Book>> books;
public MyViewModel(@NonNull Application application) {
super(application);
books = bookRepository.getBooks();
}
Когда пользователь создает новую book
из пользовательского интерфейса, я хочу, чтобы атрибут book_order
был заполнен увеличенным максимумом book_order
других книг. Чтобы лучше описать, что я хочу, смотрите следующий преудокод:
book.book_order = max(books.book_order) + 1;
Поэтому, когда есть три книги с book_order
1, 2, 3 соответственно, новая книга будет иметь этот атрибут book_order
4.
Вопрос в том, как я могу сделать это с LiveData
во ViewModel
? Я пытался использовать Transformations.map
для новых LiveData
, но этот подход вообще не работает, bookMax
кажется null
.
public void insertBook(Book book) {
LiveData<Integer> bookMax = Transformations.map(books,
list -> {
int value = 0;
for(Book b: list) {
if (value < b.getBookOrder()) {
value = b.getBookOrder();
}
}
}
);
book.setBookOrder(bookMax + 1)
bookRepository.update(book);
}
Любые идеи, как установить увеличенный максимум для новой книги? Это может быть другой подход, чем тот, который описан здесь. ViewModel
был создан для ветки логики приложения от пользовательского интерфейса. Однако, похоже, что в этом случае этого не происходит, потому что, если я хочу наблюдать ценность, мне нужно быть в Activity
. Кроме того, я не нашел никакой альтернативы, как сделать один вид получения одного значения из БД. Любая помощь приветствуется.
Использование LiveData не поможет в вашем сценарии.
LiveData в DAO выполняется в другом потоке, а новое значение публикуется в коде наблюдателя или в вашем случае с обратным вызовом Transformation.map(). Так что вам нужно получить доступ к book.id внутри Transformation.map().
Однако, если вы вставите книгу в Transformation.map(), это вызовет бесконечный цикл, поскольку при каждом обновлении записи таблицы Transformation.map() будет вызываться как LiveData>.
Итак, для вашего случая:
Обратите внимание, что ваши books
являются livedata
, поэтому могут время от времени менять свою ценность.
В то время как ваш bookMax
является единственным значением, которое должно быть рассчитано в момент вставки.
Чтобы вставить вам нужно:
val bookList: List<Book> = books.value // current value. may be null!
val bookMax: Int = bookList.maxBy { it.order }.order // find max order
// insert
val newBooks = arrayListOf(bookList)
newBooks.add(newBook)
books.value = newBooks // update your livedata
РЕДАКТИРОВАТЬ Вот Java-код
// get current value. may be null!
List<Book> bookList = books.getValue();
// so we better handle it early
if (bookList == null) {
bookList = new ArrayList<>();
}
// calculate max order
int maxOrder = -1;
for (Book book : bookList) {
if (maxOrder < book.order) {
maxOrder = book.order;
}
}
// create new book
Book newBook = new Book();
newBook.order = maxOrder + 1;
// add book to the list
bookList.add(newBook);
// do with new list whatever you want
// for example, you can update live data (if it is a MutableLiveData)
books.setValue(bookList);