Android ViewModel LiveData observe



我按照安卓开发团队提供的ViewModel实现指南进行操作。然而,我得到了意想不到的结果。我一直在上网,但运气不好。

BookMarketPojo.java

class BookMarketPojo {
private String bookTitle;
private String bookAuthor;
private String bookDescription;
private String bookPictureUrl;
private String ownerId;
private boolean sold;
public BookMarketPojo() {
}
public BookMarketPojo(String bookTitle, String bookAuthor, String bookDescription, String bookPictureUrl, String ownerId, boolean sold) {
this.bookTitle = bookTitle;
this.bookAuthor = bookAuthor;
this.bookDescription = bookDescription;
this.bookPictureUrl = bookPictureUrl;
this.ownerId = ownerId;
this.sold = sold;
}
// getters and setters
}

BookViewModel.java

public class BookViewModel extends ViewModel {
private List<BookMarketPojo> booksList = new ArrayList<>();
private final String NODE_NAME = "_books_for_sale_";
private FirebaseDatabase db = FirebaseDatabase.getInstance();
public MutableLiveData<List<BookMarketPojo>> getData() {
fetchData();
MutableLiveData<List<BookMarketPojo>> data = new MutableLiveData<>();
data.setValue(booksList);
return data;
}
private void fetchData() {
db.getReference(NODE_NAME).addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
booksList.add(dataSnapshot.getValue(BookMarketPojo.class));
}
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
}

BookMarketAdapter.java

public class BookMarketAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private List<BookMarketPojo> bookMarketPojos;
public BookMarketAdapter(Context context, List<BookMarketPojo> bookMarketPojos) {
this.context = context;
this.bookMarketPojos = bookMarketPojos;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(context).inflate(R.layout.book_market_row, parent, false);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
final BookMarketPojo book = bookMarketPojos.get(position);
((ViewHolder) viewHolder).title.setText(book.getBookTitle());
((ViewHolder) viewHolder).author.setText(book.getBookAuthor());
((ViewHolder) viewHolder).description.setText(book.getBookDescription());
Picasso.get().load(book.getBookPictureUrl()).into(((ViewHolder) viewHolder).bookImg);
}
@Override
public int getItemCount() {
return bookMarketPojos.size();
}
private class ViewHolder extends RecyclerView.ViewHolder {
TextView title, author, description;
ImageView bookImg;
public ViewHolder(View convertView) {
super(convertView);
title = convertView.findViewById(R.id.tv_title);
author = convertView.findViewById(R.id.tv_author);
description = convertView.findViewById(R.id.tv_description);
bookImg = convertView.findViewById(R.id.iv_bookImg);
}
}
}

MainActivity.java

public class MainActivity extends AppCompatActivity {
private static final String TAG = "MarketActivity";
private BookMarketAdapter myAdapter;
private RecyclerView recyclerView;
private BookViewModel bookViewModel;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.rv_bookMarket);
bookViewModel = new ViewModelProvider(this).get(BookViewModel.class);
bookViewModel.getData().observe(this, books -> {
myAdapter.notifyDataSetChanged();
});
initRecyclerView();
}
public void initRecyclerView(){
myAdapter = new BookMarketAdapter(this, bookViewModel.getData().getValue());
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(myAdapter);
}
}

预期结果:应用程序启动时会打开MainActivity,并在回收器视图中显示书籍。

实际结果:应用程序启动时打开MainActivity不显示任何内容。单击返回应用程序后关闭。当点击应用程序图标打开时,它会启动显示MainActivity,显示书籍的重复数据集。

显示结果的gif链接。

有人能发现问题出在哪里吗?为什么onCreate不在第一次启动时初始化适配器?为什么我会收到一份重复的书单?

链接到Git存储库

让我们从您的问题中分解您所写的内容以及LiveData是如何工作的,好吗?

首先,你的适配器看起来不错(大部分(,这不是问题所在。

让我们看看ViewModel,这里出了什么问题,阅读我对解决方案的内联评论:

public class BookViewModel extends ViewModel {
private List<BookMarketPojo> booksList = new ArrayList<>();
private final String NODE_NAME = "_books_for_sale_";
private FirebaseDatabase db = FirebaseDatabase.getInstance();
/** 
* The purpose of livedata is to simply emit events. 
* Therefore this can be simply written as [note the general convention used in naming]
*/
public MutableLiveData<List<BookMarketPojo>> onBookListUpdated = MutableLiveData<List<BookMarketPojo>>();
/** 
* The problem with this code, is that when you set the value initially, you only set an empty arraylist. 
* Remember, your LiveData is only a way to emit changes to a data (the data here being booksList) with the safetynet of LifeCycle Awareness
* therefore, to fetch the data, we only need to do this. 
*/
public void getData() {
fetchData()
}
private void fetchData() {
db.getReference(NODE_NAME).addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
//To remove duplicates, make sure the book isn't already present in the list. Exercise is left to you
booksList.add(dataSnapshot.getValue(BookMarketPojo.class));
//This will now trigger the livedata, with the list of the books.
onBookListUpdated.setValue(booksList)
}
@Override
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
}

最后在活动的OnCreate((中

bookViewModel.onBookListUpdated.observe(this, books -> {
myAdapter.notifyDataSetChanged();
});

此外,请查看Firebase Realtime DB Documentation for Reading Data Once,因为我相信这比只取一次书更适合您的用例!

相关内容

  • 没有找到相关文章

最新更新