Android Room 分页不起作用。

8

我正在尝试使用Android Room API分页加载SQLite中的记录。

问题在于Paging库正在将整个数据库加载到模型类中,并将其与适配器绑定,这使得UI线程跳帧。它应该加载20条记录,然后在需要时继续添加更多记录。

这是我的ViewModel类:

public class UserViewModel extends ViewModel {

    public LiveData<PagedList<User>> userList;

    public UserViewModel() {

    }

    public void init(UserDao userDao) {
        PagedList.Config pagedListConfig =
                (new PagedList.Config.Builder()).setEnablePlaceholders(true)
                        .setPrefetchDistance(10)
                        .setPageSize(20).build();

        userList = (new LivePagedListBuilder(userDao.usersByFirstName(),
                pagedListConfig))
                .build();

    }
}

分页适配器
public class UserAdapter extends PagedListAdapter<User, UserAdapter.UserItemViewHolder> {


    protected UserAdapter() {
        super(User.DIFF_CALLBACK);
    }

    @Override
    public UserItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        View view = layoutInflater.inflate(R.layout.item_user_list, parent, false);
        return new UserItemViewHolder(view);
    }

    @Override
    public void onBindViewHolder(UserItemViewHolder holder, int position) {
        User user= getItem(position);
        if(user!=null) {
            holder.bindTo(user);
        }
    }

    static class UserItemViewHolder extends RecyclerView.ViewHolder {
        TextView userName, userId;

        public UserItemViewHolder(View itemView) {
            super(itemView);
            userId = itemView.findViewById(R.id.userId);
            userName = itemView.findViewById(R.id.userName);
        }

        public void bindTo(User user) {
            userName.setText(user.firstName);
            userId.setText(String.valueOf(user.userId));
        }
    }
}

使用 RecyclerView 进行绑定:

  UserViewModel viewModel =
                ViewModelProviders
                        .of(this)
                        .get(UserViewModel.class);
        viewModel.init(userDao);
        final UserAdapter userUserAdapter = new UserAdapter();

        viewModel.userList.observe(this, pagedList -> {
            Toast.makeText(this, "Page " + pagedList.size(), Toast.LENGTH_SHORT).show();
            Log.e("Paging ", "Page " + pagedList.size());
            userUserAdapter.setList(pagedList);
        });

        recyclerView.setAdapter(userUserAdapter);

02-18 10:19:40.409 15310-15310/com.androidkt.archpaging E/Paging: 第200页

有什么想法我缺少了什么。


请检查您的RecyclerView,确保方法onMeasure的返回值不会比预期的高度要大(可能预期的高度应该是屏幕大小左右)。有时候RecyclerView的实际高度比屏幕大得多,适配器会调用getView()来绑定所有项目而不是我们可以看到的数量。这会触发DataSource查询数据库并在您想要之前绑定视图。 - Allan Veloso
3个回答

0

尝试使用userUserAdapter.setList(pagedList)方法,然后观察变化并使用监听器监听列表的变化。您需要正常初始化列表并设置recyclerview。对象列表应按照通常的方式包含在pageAdapter中。


0

您应该调用 userUserAdapter.submitList(pagedList)setList() 用于 RecyclerView.Adapter,而不是用于 PagedListAdapter


0
通过分页实现,您的结果计数应该确实是查询的完整大小(200),正如您配置的那样,RecyclerView将接收占位符null以表示其数据尚未准备好的视图。当您想要显示整个列表视图但仅在数据可用时绑定其内容时,这是有意的。但是,除非可见,否则您的RecyclerView不应为整个计数调用onCreateViewHolderonBindViewHolder
检查(设置断点)您RecyclerView上的onMeasureonLayout方法,看看该方法是否返回比预期更大的高度(可能预期值大约为屏幕大小)。有时,RecyclerView的实际高度要比屏幕大得多,并且适配器会为总项目数调用onBindViewHolder(),因为它对其是“可见的”,而不是我们可以看到的数字。这将触发DataSource查询数据库并在您想要之前绑定视图。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接