Получить одно значение из LiveData

1

У меня есть 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. Кроме того, я не нашел никакой альтернативы, как сделать один вид получения одного значения из БД. Любая помощь приветствуется.

Теги:
android-room
android-livedata
android-viewmodel

2 ответа

0

Использование LiveData не поможет в вашем сценарии.

LiveData в DAO выполняется в другом потоке, а новое значение публикуется в коде наблюдателя или в вашем случае с обратным вызовом Transformation.map(). Так что вам нужно получить доступ к book.id внутри Transformation.map().

Однако, если вы вставите книгу в Transformation.map(), это вызовет бесконечный цикл, поскольку при каждом обновлении записи таблицы Transformation.map() будет вызываться как LiveData>.

Итак, для вашего случая:

  1. Выставьте метод, который выставляет последний идентификатор книги
  2. Вставьте новую запись.
  3. Добавьте LiveData>, чтобы получать обновления и отображать в пользовательском интерфейсе.
0

Обратите внимание, что ваши books являются livedata, поэтому могут время от времени менять свою ценность.
В то время как ваш bookMax является единственным значением, которое должно быть рассчитано в момент вставки.

Чтобы вставить вам нужно:

  • получить текущий список книг
  • затем рассчитать 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);
  • 0
    Не могли бы вы предоставить код Java? Спасибо.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню