Westerlund.io
Westerlund.io

Reputation: 2833

ProgressBar not spinning during async load

When I open a Fragment I try to show a ProgressBar, populate a RecyclerView, update NotifyChange to RecyclerView and then hide the ProgressBar.

Right now the ProgressBar isn't spinning. I think it has to do with SetRecyclerViewItems being executed on the UI Thread but if I don't do that I get an error saying that the UI can only be updated in the UI thread.

Fragment:

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
            /* Initializing elements code removed */

            SetRecyclerView();

            return view;
        }

    public async override void OnStart()
            {
                base.OnStart();

                ShowProgressBar();
                await LoadAsync();
                HideProgressBar();
            }

            private async Task LoadAsync()
            {
                await Task.Run(() => {
                    SetRecyclerViewItems();
                });

            }

            private void SetRecyclerView()
            {
                mLayoutManager = new LinearLayoutManager(mRecyclerView.Context);
                mRecyclerView.SetLayoutManager(mLayoutManager);
                mAdapter = new TransactionsRecyclerAdapter(this.Activity, mTransactions, dateFormat);
                mAdapter.ItemClick += MAdapter_ItemClick;
                mRecyclerView.SetAdapter(mAdapter);
            }

            private void SetRecyclerViewItems(List<PaymentListItemViewModel> transactions = null)
            {
                Activity.RunOnUiThread(() => {

                    if (transactions == null)
                        transactions = GetTransactions();
                    mAdapter.NotifyChange(transactions);
                    SetTotal();
                });
            }

Adapter.NotifyChange

public void NotifyChange(List<PaymentListItemViewModel> transactions)
        {
            mTransactions = transactions;
            NotifyDataSetChanged();
        }

Why isn't the ProgressBar spinning? Is the way I'm populating new data to the Adapter correct (sending in a new list and then NotifyDataSetChanged?

Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/login_background">
    <RelativeLayout
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:gravity="center"
        android:layout_centerInParent="true"
        android:id="@+id/transactionsProgressBar">
        <ProgressBar
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            style="@android:style/Widget.ProgressBar.Large" />
    </RelativeLayout>
    <LinearLayout
        android:orientation="vertical"
        android:minWidth="25px"
        android:minHeight="25px"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/linearLayout4"
        android:layout_weight="1">
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerViewTransactions"
            android:layout_height="match_parent"
            android:layout_width="match_parent"
            android:scrollbars="vertical" />
    </LinearLayout>

</LinearLayout>

In OnCreateView:

mLayoutProgressBar = view.FindViewById<RelativeLayout>(Resource.Id.transactionsProgressBar);

Show/Hide ProgressBar:

private void ShowProgressBar()
                {
                    mLayoutProgressBar.Visibility = ViewStates.Visible;
                }

                private void HideProgressBar()
                {
                    mLayoutProgressBar.Visibility = ViewStates.Gone;
                }

Upvotes: 2

Views: 614

Answers (1)

Krumelur
Krumelur

Reputation: 33068

You put the loading onto a separate thread by using Task.Run() but in there you marshal back to the UI thread to update your adapter (Activity.RunOnUiThread()), this will block the UI thread and your spinner stops running.

Depending on what your SetTotal() method is doing, you should only have the call to mAdapter.NotifyChange(transactions); being executed on the UI thread.

Upvotes: 2

Related Questions