从LiveData获取一个值

问题描述 投票:2回答:5

我在LiveData的构造函数中有ViewModel for books:

LiveData<List<Book>> books;

public MyViewModel(@NonNull Application application) {
    super(application);
    books = bookRepository.getBooks();
}

当用户从UI创建新的book时,我希望属性book_order填充其他书籍的book_order增量最大值。为了更好地描述我想要的内容,请参阅以下preudocode:

book.book_order = max(books.book_order) + 1;

因此,当有三本书分别使用book_order 1,2,3时,新书将此属性设置为4。

问题是,我怎么能在qazxsw poi中用qazxsw poi做到这一点?我尝试使用qazxsw poi到新的LiveData,但这种方法根本不起作用,ViewModel似乎是Transformations.map

LiveData

任何想法如何设置增量最大值到新书?它可以是另一种方法,而不是这里描述的方法。创建bookMax是为了将应用程序逻辑与UI分开。然而,在这种情况下似乎没有这样做,因为如果我想观察价值,我需要在null。另外,我没有找到任何替代方法如何从DB获取一个值。任何帮助赞赏。

android android-room android-livedata android-viewmodel
5个回答
0
投票

请注意,你的qazxsw poi是qazxsw poi,这可能会不时改变它的价值。 哪里你的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); } 是一个值,应该在插入时计算。

要插入你需要:

  • 获取当前的书籍清单
  • 然后计算bookMax
  • 然后实际插入。
ViewModel

编辑这是Java代码

Activity

0
投票

使用LiveData对您的方案没有帮助。 DAO中的LiveData在不同的线程上执行,新值在观察者代码或您的情况下发布Transformation.map()回调。因此,您需要访问Transformation.map()中的book.id. 但是,如果您在Transformation.map()中插入book,它将触发无限循环,因为在每个表条目更新时,将调用Transformation.map(),因为LiveData>将更改。

所以,对于你的情况:

  1. 公开暴露上一本书ID的方法
  2. 插入新条目。
  3. 添加LiveData>以接收更新并在UI中显示。

0
投票

您应该在存储库中创建一个方法,从而为db提供最大数量的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

在这里,假设您使用ROOM来持久化数据库,这是可以帮助您获得最大// 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); 的查询:

book_order

如果ROOM不是你的情况那么,你可以采用另一种方法:

我们首先使用存储库方法检索列表,然后从中找到最大值,如下面的伪:

int maxOrder = bookRepository.getMaxBookOrder();

然后从中找到max,然后将其递增1:

maxOrder

即使你可以将这个查找最大值的代码移动到前面提到的存储库方法,例如:

public void insertBook(Book book) {
    int maxOrder = bookRepository.getMaxBookOrder();
    book.setBookOrder(maxOrder + 1)
    bookRepository.update(book);
}

0
投票

如果你真的想用book_order来做,你可以创建一个自定义的:

SELECT MAX(book_order) FROM Book

然后你可以创建它并使用:

List<Book> books = bookRepository.getBooks().getValue(); // Assuming getBooks() returns LiveData

您仍然可以观察到这些实时数据,因为它在添加图书时发布了public void insertBook(Book book) { List<Book> books = bookRepository.getBooks().getValue(); // calculating max order using loop int maxOrder = -1; for (Book book : books) { if (maxOrder < book.order) { maxOrder = book.order; } } book.setBookOrder(maxOrder + 1) bookRepository.update(book); } ,它会通知观察者。您可以更改它,例如,返回已添加的书等。

旁注:从public int getMaxBookOrder() { List<Book> books = getBooks().getValue(); // calculating max order using loop int maxOrder = -1; for (Book book : books) { if (maxOrder < book.order) { maxOrder = book.order; } } return maxOrder; } 延伸可能更好,因为LiveData不应该更新它的值,但在内部你发布的东西,所以它可能会令人困惑。


0
投票

方法1:您可以使用自动增量字段或class BooksLiveData(list: List<Book>) : LiveData<List<Book>>() { val initialList: MutableList<Book> = list.toMutableList() fun addBook(book: Book) { with(initialList) { // Assuming your list is ordered add(book.copy(last().bookOrder + 1)) } postValue(initialList) } } (例如val data = bookRepository.getBooks() // Make getBooks() return BooksLiveData now data.addBook(userCreatedBook) // This'll trigger observers as well )来获取initialList的功能。如果你愿意,你甚至可以将它命名为MutableLiveData。使您的模型或实体类像:

LiveData

这样,PrimaryKey在添加到数据库的每个id上都会增加。

接下来你可以得到你的qazxsw poi类:

book_order

现在,您可以通过在活动的book_order中调用以下方法,将您的列表活动订阅到此ViewModel(即让您的活动观察ViewModel):

public class Book{
    @PrimaryKey(autoGenerate = true)
    private int book_order;
    //other data members, constructors and methods
}

做这些事情,你将能够收到更新,即。每当用户将book_order添加到您的数据库时,List / Recycler视图应自动显示新添加的Book

方法2:如果这不是你想要的,你只想找到最新添加的书的顺序,你可以完全跳过第三个代码块并在ViewModel中使用以下代码:

public class MyViewModel extends AndroidViewModel {
    private BookRepository bookRepository;
    LiveData<List<Book>> books;

    public MyViewModel(@NonNull Application application) {
        super(application);
        bookRepository = AppRepository.getInstance(application.getApplicationContext());
        books = bookRepository.getBooks();
    }

}

它给出了书籍的总数。 books表中的行,然后可以从存储库调用,而这些行又可以从ViewModel调用,而ViewModel又可以从Activity调用。

方法3:如果你想要添加新书后我认为是数据库中最新书籍数量的onCreate(),你可以使用方法1,它在ViewModel中提供了Book of Book。然后,您可以从书单中获取书籍数量。

重要!无论哪种方式,您都希望在编辑器或newBook ViewModel中编辑private void initViewModel() { final Observer<List<Book>> bookObserver= new Observer<List<Book>>() { @Override public void onChanged(@Nullable List<Book> books) { bookList.clear(); bookList.addAll(books); if (mAdapter == null) { mAdapter = new BooksAdapter(bookList, YourActivity.this); mRecyclerView.setAdapter(mAdapter); } else { mAdapter.notifyDataSetChanged(); } } }; mViewModel = ViewModelProviders.of(this) .get(MyViewModel.class); mViewModel.mBooks.observe(this, notesObserver); //mBooks is member variable in ViewModel class } 方法,并使其类似于:

Book

并在您的存储库对应的插入看起来像:

Book

和相应的Dao方法:

Dao
© www.soinside.com 2019 - 2024. All rights reserved.