每3秒重新加载GridView,而不会中断UI

时间:2018-12-28 15:27:07

标签: c# xamarin asynchronous task

我有问题。

我创建了一个带有一些按钮和GridView的Android页面。现在GridView充满了我网站上的json,我想每3秒重新加载GridView,而不会降低应用程序的速度!所以我尝试了这个:

在Page1加载无效中: popChanger = (event) => { this.setState( {userInput: event.target.value} ); console.log(event.target.value); } yourCity(){ return <div> <input type='text' onChange={this.popChanger} value={this.state.userInput} /> </div> } render() { return ( <div className = "App"> {this.yourCity()} </div> ); } }

函数:

RunOnUiThread(() => LoadOrdersAsync());

问题在于所有内容都已填满,但由于该线程的原因,UI滞后了。我该如何解决这个问题?

3 个答案:

答案 0 :(得分:2)

您必须在不中断ui的情况下刷新网格视图,因为刷新网格视图必须在ui线程上完成。

如果应用太慢,那么您想立即用太多数据填充网格视图,因此需要花费一些时间来呈现所有行。

为您提供的解决方案是准备一些分页机制,我的意思是,仅加载可见的数据量+更多内容,并且当用户尝试向下滚动并且他尝试滚动超过可用行的内容时,再向您的行中添加另一行gridview,并在用户向下滚动时反复进行。

我过去有一个常见的问题,我正在编写xamarin表单应用程序,并且我有10万条记录的列表。如果您一次加载所有内容,您将挂起几秒钟,所以我想出了分页功能,并在需要时添加了更多内容,这真的很棒。

您可以为用户体验添加一些忙碌指示器。

编辑1:

首先,正如其他人已经提到的那样,您只需要使用ui线程来更新控件中的数据。我提到过分页机制(但是您还没有说出期望的行数),但是首先检查下面的代码是否仍然有问题,然后需要进行分页。您可以尝试仅用20个元素来更新列表,以测试列表是否有帮助。

//page1 load
private void Load()
{
    LoadOrdersAsync();
}

private async Task LoadOrdersAsync()
{
    while (true)
    {
        //Creating SortedList
        var SortedOrderList = //add your logic

        RunOnUiThread( ()=>        
        {
            if (OrderListAdapter == null)
            {

                //Fill the DataSource of the ListView with the Array of Names
                OrderListAdapter = new OrderListAdapter(this, SortedOrderList);
                GridviewOrders.Adapter = OrderListAdapter;
            }
            else
            {
                OrderListAdapter.refresh(SortedOrderList);
            }
        });

        // don't run again for at least 3 seconds
        await Task.Delay(3000);
    }
}

答案 1 :(得分:0)

编辑:添加了两个TODO注释,这些注释应该在线程启动和停止时打印消息。不要使用断点,它们在调试后将无济于事。如果要获得稳定的用户体验,确实需要输出错误条件。

这可能有助于输出string message

Toast.MakeText(ApplicationContext, message, ToastLength.Long).Show();

我无法回答您的问题,但是我可以尝试使您步入正轨。

按以下步骤注释或减少代码至最低限度:

public async Task LoadOrdersAsync()
{
    // TODO: print "thread started"

    while (true)
    {
        // TODO: print "RUN!"

        await Task.Delay(3000);
    }

    // TODO: print "thread stopped"
}

将TODO注释替换为实际的文本输出,例如 flash / toast 消息。

一旦确定运行正常,实际问题就出在有效载荷上。当在辅助线程中引发异常时,它们被抑制,该线程被杀死,但是没有立即输出。

将代码封装在try..catch子句中,并像以前一样输出异常消息。为了提高可用性,请将错误输出保留在适当的位置。您至少要告诉您的应用程序的未来用户,后台出现了某些问题。这就是为什么您应该将工作错误输出保持在适当位置的原因。

这是代码支架:

public async Task LoadOrdersAsync()
{
    // TODO: print "thread started"

    while (true)
    {
        try
        {
            // TODO: all your actual payload code goes here
        } catch (Exception ex)
        {
            // TODO: print ex.Message;
            break; // you may or may not want to break the loop at this point
        }

        await Task.Delay(3000);
    }

    // TODO: print "thread stopped"
}

希望这对您有所帮助!

答案 2 :(得分:0)

通常,您应该将RunOnUiThread中的操作最小化到最低限度。这意味着不应执行任何计算,而应执行与UI相关的工作。

因此,您应该执行以下操作:

var timer = new System.Threading.Timer(
{
  //Do any work that is not UI related
  RunOnUiThread(() => LoadOrders());
}, null, 0, 3000);

函数将是:

public void LoadOrders()
{

    if (OrderListAdapter == null)
    {

        //Fill the DataSource of the ListView with the Array of Names
        OrderListAdapter = new OrderListAdapter(this, SortedOrderList);
        GridviewOrders.Adapter = OrderListAdapter;
    }
    else
    {
        OrderListAdapter.refresh(SortedOrderList);
    }
}