用Xamarin显示Android ProgressBar
我正在通过Xamarin/MonoTouch(所以使用C#而不是Java)构建一个Android应用程序,并希望在应用程序与服务器通信时显示ProgressBar。我一直在尝试使用async来做到这一点,但我对线程的工作方式并没有很好的理解,而且我在过去几个小时里遇到了同样的问题 - ProgressBar在我的方法调用之后显示,而不是之前。我的代码在OnCreate()方法中,我也将其重写为异步。这是它:用Xamarin显示Android ProgressBar
loginButton.Click += async (sender, e) =>
{
progbar.Visibility = ViewStates.Visible;
var userFetcher = new UserFetcher();
var json = await userFetcher.FetchUserDetailsAsync(/*parameters*/);
//the above method is async and returns a Task<JsonValue>
ParseUserDetails(json); //another method I created
progbar.Visibility = ViewStates.Invisible;
//do some stuff using the parsed data
};
我遇到的问题是,FetchUserDetailsAsync似乎阻止我的线程。我一直在通过关闭服务器来测试它,以便它需要很长的响应时间(但即使当我测试像Thread.Sleep(5000)这样的东西时,我也有同样的问题)。在调用该方法之后,它会一个接一个地运行progbar.Visibility = ViewStates.Visible;
和progbar.Visibility = ViewStates.Invisible;
- 我知道这是因为当我注释掉Invisible部分时,ProgressBar在我的方法从服务器获得“响应”后出现。编译器也一直给我发送消息,如“跳过67帧!应用程序可能在其主线程上做了太多工作。”
就像我之前说过的,我对线程并不是很有经验,所以很可能我只是天真地做错了什么。有没有人有解决这个问题?
编辑:这里为FetchUserDetailsAsync源代码:
public async Task<JsonValue> FetchUserDetailsAsync(string url, string username, string password)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
request.ContentType = "application/json";
request.Method = "GET";
string myBasicHeader = AuthenticationHelper.MakeHeader(username, password);
request.Headers.Add("Authorization", "Basic " + myBasicHeader);
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
JsonValue jsonDoc = await Task.Run(() => JsonObject.Load(stream));
return jsonDoc;
}
}
}
catch (WebException e)
{
Console.WriteLine(e.ToString());
if (e.Status == WebExceptionStatus.ProtocolError)
{
var response = e.Response as HttpWebResponse;
if (response != null)
{
Console.WriteLine("HTTP Status Code: " + (int)response.StatusCode);
}
else
{
Console.WriteLine("No http status code available");
}
}
return null;
}
}
它看起来像要么FetchUserDetailsAsync或ParseUserDetails阻止UI线程。因为Task.Sleep(5000)正在同步运行。尝试等待Task.Delay(5000);在FetchUserDetailsAsync的行中查看进度条是否显示。如果是这样,那么你可能需要进入FetchUserDetailsAsync实现,以确保它实现异步
我想出了这个问题。我在我的FetchUserDetailsAsync方法中调用GetResponse()
而不是GetResponseAsync()
。
非常有趣。当我尝试Task.Delay()时,事情就像我想的那样工作。我正在调查FetchUserDetailsAsync以查看可能存在的问题 – Captain
我花了一些时间查看FetchUserDetailsAsync(),我无法真正了解可能是什么问题。它使用异步调用来'等待Task.Run()'。代码的另一半只是捕获异常,如果情况如此,则返回null。使用'await Task.Yield()'实际上给ProgressBar时间显示,但它不动画 - 就像FetchUserDetailsAsync()在某种程度上仍然同步运行一样。我将在OP中发布这些数据的源代码 – Captain