您已标记async-await
并在标题中写入异步。但是,所有代码都在主线程上运行,而不是异步运行。
而不是在 ViewModel 的构造函数中加载数据。我强烈建议您使用生命周期事件,例如OnAppearing
在你的Page
并开火ICommand
异步加载数据。
另外我会改用HttpClient
及其漂亮的异步 API。所以像这样:
public class GalleryService
{
private HttpClient _httpClient;
public GalleryService()
{
_httpClient = new HttpClient();
}
public async Task<IEnumerable<picdata>> GetImageList(string pCode, string gCode, string gUrl)
{
var response = await _httpClient.GetAsync(gUrl).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
var deserialized = JsonConvert.DeserializeObject<JsonTxt>(json);
var images = new List<picdata>();
foreach(var img in deserialized.Files)
{
images.Add(new picdata()
{
ImageName = img.file,
BaseUrl = deserialized.Settings.Path.ToString(),
ThumbUrl = deserialized.Settings.Path.ToString() + "/thumbs" + img.file
});
}
return images;
}
return new picdata[0]; // return empty set
}
}
和视图模型:
public class GalleryViewModel
{
private GalleryService _galleryService;
public ObservableCollection<picdata> Galleries { get; } = new ObservableCollection<picdata>();
public ICommand GetImagesCommand { get; }
public GalleryViewModel(string pCode, string gCode, string gUrl)
{
_galleryService = new GalleryService();
GetImagesCommand = new Command(async () => DoGetImagesCommand(pCode, gCode, gUrl));
}
private async Task DoGetImagesCommand(string pCode, string gCode, string gUrl)
{
var images = await _galleryService.GetImageList(pCode, gCode, gUrl);
foreach(var image in images)
Galleries.Add(image);
}
}
然后在你的OnAppearing()
在您的页面上覆盖,您可以调用类似以下内容的内容:(BindingContext as GalleryViewModel).GetImagesCommand.Execute(null);
确保您设置了BindingContext
在尝试调用命令之前。这可以在 Page 构造函数中完成:
BindingContext = new GalleryViewModel();
这样,在图像下载完成之前,您就不会阻塞整个 UI。或者,您可以使用以下命令启动任务Task.Run
在 ViewModel 的构造函数中。但是,您必须将 ObservableCollection 的数量编组到 UI 线程。