当我在ViewModel初始化期间尝试加载API端点的内容时,我在Xamarin.Android/iOS上遇到了MvvmCross的问题。我正在从API加载一个区域的当前天气预报,我用异步方法编写它,并从初始化生命周期回调中调用它。到目前为止,我已经尝试过Stat()和Init()。在这两种情况下,我的UI都加载了来自ViewModel的值,但随后立即冻结。如果我在异步代码中的任何地方设置断点,断点捕获并在播放时,它按预期工作。我怀疑某种情况下某种情况,但我不确定如何避免它并在我的ViewModel / View出现时加载数据。这是我的代码:
// WeatherService的
public async Task<WeatherStatus> GetWeatherStatus (string zip)
{
var client = new HttpClient();
var msg = await client.GetAsync(string.Format(WeatherApiUrlBase, WeatherApiKey, zip));
if (msg.IsSuccessStatusCode)
{
using (var stream = await msg.Content.ReadAsStreamAsync())
{
using (var streamReader = new StreamReader(stream))
{
var str = await streamReader.ReadToEndAsync();
var obj = JsonConvert.DeserializeObject<WeatherStatus>(str);
return obj;
}
}
}
return null;
}
// FirstViewModel
public async override void Start ()
{
base.Start ();
FetchWeatherStatus ();
}
private async void FetchWeatherStatus() {
var weatherData = await _service.GetWeatherStatus ("84043");
FeelsLike = weatherData.current_observation.feelslike_f;
}
这个异步代码可以通过按下按钮MvxCommand就好了;但是如果从构造函数,Init或Start它调用,每次如果我在那里没有断点那么会冻结UI。如果有人能帮助我找到我做错的事情,我会很感激。感谢。
修改
我发现当我没有调试时,应用程序似乎正常运行。我从Xamarin Studio停止调试器并重新启动应用程序,它运行完美。
这里要求的是我用于绑定FeelsLike的XML:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
local:MvxBind="Text FeelsLike" />
我也试过添加.ConfigureAwait(false);我所有的等待电话,似乎更糟。 UI永远不会被初始化,它位于黑屏上,而不仅仅是我的常规UI冻结。
这可能会有所帮助,但这里有一个指向我的项目文件夹的链接(因为我刚刚学习这个框架,所以它非常小): http://goo.gl/SJscZA
编辑2
问题可能出在我的HttpClient代码中?我用一个简单的Task.Delay(5000)替换它并返回一个空的WeatherStatus以查看发生了什么并且它没有冻结。我将研究以另一种方式获取数据。我是Xamarin的新手,所以我愿意接受这里的建议。谢谢。这是我的Task.Delay()代码的片段:
public async Task<WeatherStatus> GetWeatherStatus (string zip)
{
await Task.Delay (5000);
return new WeatherStatus ();
}
答案 0 :(得分:3)
通常,这意味着您需要为每个.ConfigureAwait(false)
添加await
,以防止同步上下文出现死锁:
public async Task<WeatherStatus> GetWeatherStatus (string zip)
{
var client = new HttpClient();
var msg = await client.GetAsync(string.Format(WeatherApiUrlBase, WeatherApiKey, zip)).ConfigureAwait(false);
if (msg.IsSuccessStatusCode)
{
using (var stream = await msg.Content.ReadAsStreamAsync().ConfigureAwait(false))
{
using (var streamReader = new StreamReader(stream))
{
var str = await streamReader.ReadToEndAsync().ConfigureAwait(false);
var obj = JsonConvert.DeserializeObject<WeatherStatus>(str);
return obj;
}
}
}
return null;
}