How to keep UI unlocked while initializing recyclerview adapter?

Viewed 579

How to initialize RecyclerView adapter without locking the UI? All I want to do is show progress bar while adapters views are being created and after that operation is done hide the the progress bar and show the completed recyclerview adapter.

The problem is when i .setAdapter(), UI freezes for a short while and progressbar becomes frozen during that moment.

I am not able to figure out how to solve this issue since view related operations have to be done in UI thread.

Any ideas?

Code: Loading data from db:

dataLoader = Observable
                .just(getApplication().getDbHelper())
                .map(this::doInBackground)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(this::onPostExecute);

onPostExecute method:

entriesAdapter = new EntriesAdapter(getApplication(), loadedData.entries);
this.loadedData = loadedData;
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
        viewHolder.entries.setHasFixedSize(true);
        viewHolder.entries.setLayoutManager(layoutManager);
        viewHolder.entries.setItemAnimator(new DefaultItemAnimator());
        viewHolder.entries.setAdapter(entriesAdapter);

Adapters code:

public class EntriesAdapter extends RecyclerView.Adapter<EntriesAdapter.ViewHolder> {
    private BudgeterApplication app;
    private List<Expense> entries;
    private CompositeDisposable compositeDisposable;

    public EntriesAdapter(BudgeterApplication app, List<Expense> entries) {
        this.app = app;
        this.entries = entries;
    }

    public void setEntries(List<Expense> entries) {
        this.entries = entries;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        return new ViewHolder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.expense_list_row, viewGroup, false));
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {
        Expense expense = entries.get(i);

        viewHolder.getSumText().setText(BigDecimalUtils.convertToCurrencyString(expense.getSum()));
        viewHolder.getCommentText().setText(expense.getComment() == null ? "" : expense.getComment());
        viewHolder.getDateText().setText(DateUtils.convertToString(expense.getTimeStamp(), "MM-dd HH:mm"));
    }

    @Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        compositeDisposable = new CompositeDisposable();
        super.onAttachedToRecyclerView(recyclerView);
    }

    @Override
    public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
        if (compositeDisposable != null && !compositeDisposable.isDisposed()) {
            compositeDisposable.dispose();
        }
        super.onDetachedFromRecyclerView(recyclerView);
    }

    @Override
    public int getItemCount() {
        return entries.size();
    }


    @Getter
    class ViewHolder extends RecyclerView.ViewHolder {

        private View parent;
        private TextView sumText;
        private TextView commentText;
        private TextView dateText;

        ViewHolder(@NonNull View itemView) {
            super(itemView);
            this.parent = itemView;
            init();
        }

        private void init() {
            sumText = parent.findViewById(R.id.sum_text);
            commentText = parent.findViewById(R.id.comment_text);
            dateText = parent.findViewById(R.id.date_text);
        }
    }
}
1 Answers

It looks like you may be doing too much heavy processing while constructing RecycerView items.

Also, make sure to set this property of recycler view recyclerView.setHasFixedSize(true)

If this does not help I would suggest to look at the simplest example here https://developer.android.com/guide/topics/ui/layout/recyclerview

This will work fine, so you can compare it to your code

Related