Hitesh Sahu
Hitesh Sahu

Reputation: 45140

Android Room Pagination not working

I am trying to use android Room API to load records from sQlite in pages.

The issue is Paging library is loading entire database into model class and binding it with the adapter which is making UI thread skip frames. It suppose to load 20 records and then keep on adding more when required

This is my view model class

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();

    }
}

Paged adapter

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));
        }
    }
}

Binding with recycler View:

  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: Page 200

Any idea what I am missing.

Upvotes: 9

Views: 6465

Answers (3)

Movses Arakelyan
Movses Arakelyan

Reputation: 64

You should call userUserAdapter.submitList(pagedList). setList() is used for RecyclerView.Adapter not for PagedListAdapter.

Upvotes: 1

Đốc.tc
Đốc.tc

Reputation: 923

try userUserAdapter.setList(pagedList); put out observe . observe use listner list change . You . You need to initialize the list and set up recyclerview normally . The object list should be included in the pageAdapter in the usual way

Upvotes: 1

Allan Veloso
Allan Veloso

Reputation: 6389

By the paging implementation, your result count should indeed be the full size of the query (200), as you configured to do so, the RecyclerView will receive placeholders null for the views which data is not ready yet. This is intended for when you want to show the whole list views but only bind the content of it when the data is available. But your RecyclerView should not call onCreateViewHolder and onBindViewHolder for the entire count unless it is visible.

Check (put a breakpoint) the method onMeasure or onLayout on your RecyclerView to see if the method is not returning a bigger height than expected (probably the expected is something around the size of your screen). Sometimes the actual height of RecyclerView is much bigger than the screen and the adapter call onBindViewHolder() for the total number of items because it's "visible" to it instead of the number we can see. This would trigger the DataSource to query the database and bind the views before you want.

Upvotes: 1

Related Questions