【问题标题】:ProgressBar not spinning during async loadProgressBar 在异步加载期间不旋转
【发布时间】:2017-01-26 22:55:24
【问题描述】:

当我打开Fragment 时,我尝试显示ProgressBar,填充RecyclerView,将NotifyChange 更新为RecyclerView,然后隐藏ProgressBar

现在 ProgressBar 没有旋转。我认为这与在 UI 线程上执行的 SetRecyclerViewItems 有关,但如果我不这样做,我会收到一条错误消息,提示 UI 只能在 UI 线程中更新。

片段:

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

为什么 ProgressBar 不旋转? 我向适配器填充新数据的方式是否正确(发送新列表,然后发送NotifyDataSetChanged

布局:

<?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>

在 OnCreateView 中:

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

显示/隐藏进度条:

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

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

【问题讨论】:

  • 显然这是因为 SetRecyclerViewItems 中的 RunOnUiThread 只是 Handler.post 的快捷方式,它立即返回并使所有异步、等待和任务无用
  • 什么是 GetTransactions 和 SetTotal,它们需要多长时间?
  • 这就是我的想法,但正如我所说,如果我不在 UI 线程中运行它会抛出一个异常,说“只能在 UI 线程中更改视图”。如何分别运行两个 UI 项(ProgressBar 和 SetRecyclerViewItems)?
  • @Luke 在创建适配器时填充了一个空列表,然后我使用 GetTransactions 获取要在 ReyclerView 中使用的数据。处理大约需要 1 秒。 SetTotal 目前是一个空方法。
  • 你显然应该只在任务中运行 GetTransactions 并等待它的结果

标签: android xamarin


【解决方案1】:

您使用Task.Run() 将加载放到一个单独的线程中,但在那里您将编组回到 UI 线程以更新您的适配器 (Activity.RunOnUiThread()),这将阻塞 UI 线程并且您的微调器停止运行。

根据您的 SetTotal() 方法正在做什么,您应该只在 UI 线程上执行对 mAdapter.NotifyChange(transactions); 的调用。

【讨论】:

  • 感谢您的宝贵时间。我在 OnBindViewHolder 中进行了很多计算(它阻塞了 UI 线程),在您的帮助下,我现在异步加载所有数据,并且只将实际数据发送到 RecyclerView。
猜你喜欢
  • 1970-01-01
  • 2018-06-25
  • 2012-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-12
  • 1970-01-01
  • 2017-02-08
相关资源
最近更新 更多