Gra*_*mbo 3 c# android asynchronous mvvmcross xamarin
当我尝试在 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;
}
Run Code Online (Sandbox Code Playgroud)
//第一个视图模型
public async override void Start ()
{
base.Start ();
FetchWeatherStatus ();
}
private async void FetchWeatherStatus() {
var weatherData = await _service.GetWeatherStatus ("84043");
FeelsLike = weatherData.current_observation.feelslike_f;
}
Run Code Online (Sandbox Code Playgroud)
这个异步代码可以通过一个按钮按下 MvxCommand 就可以了;但是如果从构造函数、Init 或 Start 调用,如果我在某处没有断点,它每次都会冻结 UI。如果有人能帮我找出我做错了什么,我将不胜感激。谢谢。
编辑
我发现当我不调试时,该应用程序似乎运行正常。我从 Xamarin Studio 停止调试器并重新启动应用程序,它运行完美。
按照这里的要求是我用于绑定 FeelsLike 的 XML:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
local:MvxBind="Text FeelsLike" />
Run Code Online (Sandbox Code Playgroud)
我也试过添加 .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 ();
}
Run Code Online (Sandbox Code Playgroud)
通常,这意味着您需要添加.ConfigureAwait(false)到 every 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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2108 次 |
| 最近记录: |