【问题标题】:Async API call in separate function单独函数中的异步 API 调用
【发布时间】:2018-01-03 22:38:44
【问题描述】:

我有一个页面,我在其中使用OnAppearing 方法从 API 检索数据:

protected override async void OnAppearing()
{
    var content = await _client.GetStringAsync(Url);
    var footmarks = JsonConvert.DeserializeObject<List<Footmark>>(content);
    _footmarks = new ObservableCollection<Footmark>(footmarks);
    listView.ItemsSource = _footmarks;

    base.OnAppearing();
}

这很好用,但是在同一页面上我有 2 个事件处理程序,我还需要在其中进行相同的 API 调用。所以最好把它移到一个函数中。但是我该怎么做呢,因为事件处理程序不能异步?

所以理想情况下我会有这样的OnAppearing:

protected override async void OnAppearing()
{
    listView.ItemsSource = GetFootmarks();

    base.OnAppearing();
}

然后是调用相同方法的事件处理程序:

void Handle_Refreshing(object sender, System.EventArgs e)
{
    listView.ItemsSource = GetFootmarks();
    listView.EndRefresh();
}

我该怎么做?

【问题讨论】:

    标签: c# xamarin xamarin.forms async-await


    【解决方案1】:

    我会走那条路:

    将您的 api 调用提取到单个方法中:

    async Task<List<Footmark>> GetFootMarksAsync()
    {
        var content = await _client.GetStringAsync(Url);
        return JsonConvert.DeserializeObject<List<Footmark>>(content);
    }
    

    这个方法可以在OnAppearing中调用

    protected override async void OnAppearing()
    {
        _footmarks = new ObservableCollection<Footmark>(await GetFootMarksAsync());
    
        listView.ItemsSource = _footmarks;
    
        base.OnAppearing();
    }
    

    在 EventHandler 中也可以这样使用。唯一的变化是使用 async 关键字标记处理程序。

    async void Handle_Refreshing(object sender, System.EventArgs e)
    {
        _footmarks = new ObservableCollection<Footmark>(await GetFootMarksAsync());
    
        listView.ItemsSource = _footmarks;
        listView.EndRefresh();
    }
    

    【讨论】:

      【解决方案2】:

      所以最好把它移到一个函数中。

      将重复的功能提取到自己的功能中是一个明智的选择。

      async Task<ObservableCollection<Footmark>> GetFootmarks() {
          var json = await _client.GetStringAsync(Url);
          return JsonConvert.DeserializeObject<ObservableCollection<Footmark>>(json);
      }
      

      这将允许您在整个依赖类中调用它。

      您甚至应该考虑将其提取到自己的服务中,以便在应用程序的其他部分重用。

      public interface IFoomarkService {
          Task<ObservableCollection<Footmark>> GetFootmarks();
      }
      

      但是我该怎么做呢,因为事件处理程序不能异步?

      事件处理程序可以设为异步。

      参考Async/Await - Best Practices in Asynchronous Programming

      避免使用async void,唯一的例外是实际的事件处理程序。

      OnAppearing() 不幸的是不是一个事件处理程序,而是一个实际的虚拟方法。

      不过,Appearing 事件是在框架调用 OnAppearing 之后引发的,这意味着您可以在那里订阅该事件,并在引发该事件时在 actual 事件处理程序中执行异步操作.

      protected override void OnAppearing() {
          this.Appearing += Page_Appearing; //Subscribe to event
          base.OnAppearing();
      }
      
      protected async void Page_Appearing(object sender, EventArgs args) {
          listView.ItemsSource = await GetFootmarks(); //get data asynchronously
          //this.Appearing -= Page_Appearing; //Unsubscribe (OPTIONAL but advised)
      }
      
      protected async void Handle_Refreshing(object sender, System.EventArgs e) {
          listView.ItemsSource = await GetFootmarks(); //get data asynchronously
          listView.EndRefresh();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-02-26
        • 1970-01-01
        • 2020-06-11
        • 2019-01-20
        • 2012-07-25
        • 2021-01-30
        • 2015-03-19
        相关资源
        最近更新 更多