【问题标题】:How to use a loading spinner for two async tasks consecutively如何连续使用加载微调器执行两个异步任务
【发布时间】:2014-12-16 22:32:47
【问题描述】:

目前我有两个独立的异步任务发出不同的网络请求。执行异步任务时,会显示加载微调器。现在我应该在第一个异步任务中添加第二个异步任务,第二个依赖于第一个。

我的主要问题是加载微调器,同时总结了两个异步调用。 Hide() 上有一个淡出动画,设置为 0.5 秒。因此,微调器在短时间内显示了两次,这看起来有点难看。如果我跳过动画,我会得到闪烁效果。

也许我错了,我应该转向正常的同步请求,但我不想阻塞 UI 线程。我不知道我应该搜索什么。这是我目前要做的,是一个简化的版本:

public async void showList()
{
    List<Car> carList = new List<Car>();
    carList = await GetCarListTask();
    List<string> manufacturers = extractIDs(carList);
    List<Manufacturer> manufacturerList = await GetManufacturerListTask(manufacturers);
    Table.Show(carList, manufacturerList);
}

public async Task<List<Car>> GetCarListTask(){
    LoadingOverlay loadingOverlay = new LoadingOverlay ();
    List<Car> carList = new List<Car>();

    try{
        loadingOverlay.Show();
        carList = await Task.Run(() => manager.GetCarList());
        loadingOverlay.Hide();
        return carList;
    }
    catch(Exception ex)
    {
        alert.Show("Something went wrong");
        loadingOverlay.Hide();
    }

    return carList;
}

public async Task<List<Manufacturer>> GetManufacturerListTask(List<string> manufacturerID){
    LoadingOverlay loadingOverlay = new LoadingOverlay ();
    List<Manufacturer> manufacturerList = new List<Manufacturer>();

    try{
        loadingOverlay.Show();
        manufacturerList = await Task.Run(() => manager.GetManufacturerList(manufacturerID));
        loadingOverlay.Hide();
        return manufacturerList;
    }
    catch(Exception ex)
    {
        alert.Show("Something went wrong");
        loadingOverlay.Hide();
    }

    return manufacturerList;
}

如您所见,LoadingOverlay() 是为每个请求独立创建的,并且取决于当前视图。 Show() 实际上是 this.NavigationController.View.InsertSubviewBelow(loadingOverlay,this.NavigationController.NavigationBar) 的替代品,唯一的中心位置是 AppDelegate,但我认为它无法访问我的每个导航控制器使用(模态视图,弹出框,...)。

我应该如何解决这个问题?

编辑:

目前我没有显示第二个加载微调器。如果用户比请求更快会发生什么会很有趣......那么我应该让第二次调用同步吗?

我想到的另一个选择是重新设计LoadingOverlay(),使闪烁不会那么明显。最好的解决方案是有一个加载类,它始终显示加载微调器,直到所有连续的请求都完成。但我不知道这样一个集中的实例会是什么样子。一个简单的解决方案是将两个调用汇总为一个方法,但您必须了解返回类型。

【问题讨论】:

  • 使用一个整数,当您开始任务时递增,任务完成时递减。当计数从 0 变为 1 时显示微调器。当计数从 1 变为 0 时,隐藏微调器。对于所有其他值什么都不做。
  • @Paulw11:感谢您的回复。我仍然不知道的是如何在当前视图上显示微调器。 AppDelegate 将是中心位置,但它只能访问我的主导航控制器。如果我在顶部弹出一个模态视图,我将创建一个新的导航控制器。我应该如何在新创建的导航控制器上显示微调器?
  • 我假设您将从正在启动异步任务的视图控制器传递您想要覆盖的视图。
  • 这是一个选择。

标签: c# ios asynchronous async-await loading


【解决方案1】:

我不明白为什么不能将显示/隐藏逻辑移至调用方法:

public async Task ShowListsAsync()
{
  LoadingOverlay loadingOverlay = new LoadingOverlay ();
  loadingOverlay.Show();
  try
  {
    List<Car> carList = await Task.Run(() => manager.GetCarList());
    List<string> manufacturers = extractIDs(carList);
    List<Manufacturer> manufacturerList = await Task.Run(() => manager.GetManufacturerList(manufacturers));
    Table.Show(carList, manufacturerList);
  }
  catch
  {
    alert.Show("Something went wrong");
  }
  finally
  {
    loadingOverlay.Hide();
  }
}

也许这个例子过于简单了,因为某些原因这不起作用。

另外,作为旁注:

我有两个独立的异步任务发出不同的网络请求

Web 请求本质上是异步的。如果您使用类似HttpClient 的东西,那么从manager 公开GetCarList/GetManufacturerList 的异步版本应该很简单。这将消除对Task.Run 的需要:

List<Car> carList = await manager.GetCarListAsync();
List<string> manufacturers = extractIDs(carList);
List<Manufacturer> manufacturerList = await manager.GetManufacturerListAsync(manufacturers);

【讨论】:

  • 现在我根据您的建议重新构建了我的代码。 WebRequest 用于我的案例。你说得对,网络请求是异步的,但我不知道我应该在库上更改什么以便获得异步版本。
  • @testing:我推荐使用HttpClient nuget library,即supports Xamarin
猜你喜欢
  • 1970-01-01
  • 2020-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-11
  • 1970-01-01
  • 2018-10-18
  • 1970-01-01
相关资源
最近更新 更多