我有一个页面,我在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();
}
我该怎么做?
答案 0 :(得分: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();
}
答案 1 :(得分:1)
所以最好把它移到一个函数中。
将重复的功能提取到自己的功能中是明智的选择。
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
事件,这意味着您可以在那里订阅事件并在实际事件处理程序中执行异步操作提出时的那个事件。
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();
}