【发布时间】:2014-03-01 19:31:00
【问题描述】:
当我在 ViewModel 初始化期间尝试加载 API 端点的内容时,我遇到了 Xamarin.Android/iOS 上的 MvvmCross 问题。我正在从 API 加载某个区域的当前天气预报,并将其写入异步方法,并从初始化生命周期回调中调用它。到目前为止,我已经尝试过 Stat() 和 Init()。在这两种情况下,我的 UI 都加载了 ViewModel 中的值,但随后立即冻结。如果我在异步代码的任何位置设置断点,断点就会捕获并在播放时,它会按预期工作。我怀疑某处存在某种竞争条件,但我不确定如何避免它并在我的 ViewModel/View 出现时加载数据。这是我的代码:
//天气服务
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() 代码的 sn-p:
public async Task<WeatherStatus> GetWeatherStatus (string zip)
{
await Task.Delay (5000);
return new WeatherStatus ();
}
【问题讨论】:
-
我看不出这段代码会导致挂起的任何原因。根据您的描述,这听起来像是活动的
OnCreate/OnStart/OnResume期间的竞争条件。您能否编辑您的问题以显示FeelsLike的 UI 绑定是什么样的? (我怀疑这会有所帮助 - 但我有希望!)作为一种潜在的调试方法,您可以尝试将跟踪添加到 VM 方法和OnXXX覆盖。对于变通方法,您可以使用ConfigureAwait将工作从 UI 线程中推送出去,或者您可以尝试将DelayedStart添加到 VM 并从OnResume调用它。
标签: c# android asynchronous xamarin mvvmcross