我试图从我之前写过的网络API中获取一个列表。然后我将在Xamarin.Forms ListView中使用该列表。我的代码在这里:
public static class DataSource
{
public static async Task<Restoran[]> GetRestoransAsync()
{
// ... Use HttpClient.
using (HttpClient client = new HttpClient())
using (HttpResponseMessage response = await client.GetAsync(page))
using (HttpContent content = response.Content)
{
// ... Read the string.
string result = await content.ReadAsStringAsync();
var restorans = JsonConvert.DeserializeObject<Restoran[]>(result);
return restorans;
}
}
}
我的ContentPage:
public class MenuPage : ContentPage
{
ListView listView;
List<Restoran> restorans = new List<Restoran>();
async Task LoadRestorans()
{
restorans = (await DataSource.GetRestoransAsync()).ToList();
}
public MenuPage(string masa)
{
var loadData = LoadRestorans();
loadData.Wait();
listView = new ListView(ListViewCachingStrategy.RecycleElement)
{
ItemsSource = restorans,
ItemTemplate = new DataTemplate(() => {
var nativeCell = new CustomCell();
return nativeCell;
})
};
}
}
但是当我调试这段代码时,&#34; LoadRestorans()&#34;方法在&#34; restorans&#34;的初始化之前调用。名单。我想我不了解异步方法的心态。我该怎么办?
答案 0 :(得分:1)
您有两种选择。
使用异步工厂方法
创建页面public class MenuPage : ContentPage {
ListView listView;
List<Restoran> restorans = new List<Restoran>();
private async Task LoadRestoransAsync() {
restorans = (await DataSource.GetRestoransAsync()).ToList();
listView = new ListView(ListViewCachingStrategy.RecycleElement) {
ItemsSource = restorans,
ItemTemplate = new DataTemplate(() => {
var nativeCell = new CustomCell();
return nativeCell;
})
};
}
public MenuPage(string masa) {
//...
}
public static async Task<MenuPage> CreateMenuPageAsync(string masa) {
var page = new MenuPage(masa);
await page.LoadRestoransAsync();
return pagel
}
}
然后在其他异步事件处理程序中使用它
var page = await MenuPage.CreateMenuPageAsync("<masa here>");
或强>
在OnAppearing
事件中执行此操作。
订阅页面/视图的Appearing
事件
protected override void OnAppearing() {
this.Appearing += Page_Appearing;
}
并在实际的偶数处理程序上调用异步代码
private async void Page_Appearing(object sender, EventArgs e) {
//...call async code here
//unsubscribing from the event
this.Appearing -= Page_Appearing;
}
完整的课程看起来像这样
public class MenuPage : ContentPage {
ListView listView;
List<Restoran> restorans = new List<Restoran>();
private async Task LoadRestoransAsync() {
restorans = (await DataSource.GetRestoransAsync()).ToList();
listView = new ListView(ListViewCachingStrategy.RecycleElement) {
ItemsSource = restorans,
ItemTemplate = new DataTemplate(() => {
var nativeCell = new CustomCell();
return nativeCell;
})
};
}
public MenuPage(string masa) {
//...
}
protected override void OnAppearing() {
this.Appearing += Page_Appearing;
}
private async void Page_Appearing(object sender, EventArgs e) {
//...call async code here
await LoadRestoransAsync();
//unsubscribing from the event
this.Appearing -= Page_Appearing;
}
}
之前发生的事情是通过调用.Wait()
,这是一个阻塞调用,该类混合了异步和阻塞调用(如.Result
和.Wait()
),这可能导致死锁。因此,当您尝试测试时,为什么您无法通过该方法。
答案 1 :(得分:0)
在restorans
之前调用,因为在初始化属性之前调用了构造函数MenuPage
。
我建议
public class MenuPage : ContentPage
{
ListView listView;
List<Restoran> restorans;
async Task<Restoran[]> LoadRestorans()
{
return await DataSource.GetRestoransAsync();
}
public MenuPage(string masa)
{
this.restorans = LoadRestorans().GetAwaiter().GetResult().ToList();
listView = new ListView(ListViewCachingStrategy.RecycleElement)
{
ItemsSource = this.restorans,
ItemTemplate = new DataTemplate(() => {
var nativeCell = new CustomCell();
return nativeCell;
})
};
}
}
注意:我没有编译这段代码,但根据我的理解,这应该是正确的代码。