在HttpClient异常(Xamarin Android)上显示AlertDialog
我的Xamarin Android应用程序使用Web服务,它使用HttpClient连接到它。在没有连接的情况下(例如,当用户没有小区或WiFi连接时),会引发一些问题。我使用async/await从服务器获取数据。下面是从我的代码的摘录:在HttpClient异常(Xamarin Android)上显示AlertDialog
public async Task<String> doLogin(string username, string password)
{
String url = Constants.loginEndpoint + username + "/" + password + "/";
var uri = new Uri(string.Format(url, string.Empty));
return_string = "";
try
{
var response = await GetAsync(uri);
if (response.IsSuccessStatusCode)
{
return_string = "success";
// Process the positive response here
else
{ }
}
catch (Exception ex)
{
throw new ConnectionException();
}
return return_string;
}
我定义了一个custon ConnectionException并要显示一个AlertDialog给用户,告知他们,该请求失败,原因是没有任何联系。用户点击确定后,我想关闭应用程序。我试图以下面的方式显示警告对话框,但它不起作用:
public class ConnectionException : Exception
{
public ConnectionException()
{
AlertDialog.Builder alert = new AlertDialog.Builder(myApp.Context);
alert.SetTitle("Failure");
alert.SetMessage("Request failed. No connection.");
alert.SetPositiveButton("OK", (senderAlert, args) =>
{
});
Dialog dialog = alert.Create();
dialog.Show();
}
public ConnectionException(string message)
: base(message)
{ }
public ConnectionException(string message, Exception innerException)
: base(message, innerException)
{ }
}
这是正确的做法吗?可能不会,因为它不工作。我将不胜感激任何帮助如何实现这一目标。另外,我还没有考虑太多,但这是处理这种异常的首选方法吗?
假设你myApp.Context
是Activity
,它没有备用堆栈,你可以叫Finish()
var context = myApp.Context; // this needs to be an Activity-based context...
context.RunOnUiThread(() =>
{
var alertDialog = new AlertDialog.Builder(context)
.SetTitle("Failure")
.SetMessage("Request failed. No connection.")
.SetPositiveButton("OK", (senderAlert, args) =>
{
context.Finish();
})
.Create();
alertDialog.Show();
});
这是正确的解决方案!谢谢! – jkwi
您是否在多个地方重复使用这个异常,或者这是一次性的? 如果你只使用这个异常一次,没有真正的理由来建立你自己的。 你可能只是捕获异常并从你的catch内发布你的警报。
我知道这不是一个漂亮的写法,但如果它工作,为什么不使用它。
备注: DisplayAlert对您来说可能更容易。这将是一个班轮。
例子:
await DisplayAlert("Failure","Request failed. No connection.", "Ok");
你正在处理可能发生的错误的方式包含多个问题,由于几个原因而不是正确的方法。
第一:您的代码不遵循C-Sharp惯例并且包含多种代码异味。我向你展示一个更好,更被接受的风格。
1)C#中的方法通常以大写字母开头。 doLogin
变为Login
2)要创建一个新的Uri实例,您不需要格式化您的url-string。 string.Empty不会被使用。所以代码可以简化为await GetAsync(new Uri(...));
3)return_string似乎没有以任何方式在方法外部使用。它是string.Empty或“成功”。为什么不把它切换到布尔?这样您可以轻松检查登录是否成功。返回类型变成bool而不是字符串。
的方法现在看起来是这样的:
public async Task<bool> Login(string username, string password)
{
//TODO: Do parameter check for username and password
try
{
var response = await GetAsync(new Uri(Constants.loginEndpoint + username + "/" + password + "/"));
if (response.IsSuccessStatusCode)
{
// Process the positive response here
return true;
}
else
{
return false;
}
}
catch (Exception ex)
{
throw new ConnectionException();
}
return false;
}
其次,由@Jason提到,异常不应包含任何UI或业务逻辑。考虑以下内容,这将打破目前的实施。
public async Task<bool> Login(string username, string password)
{
var connectionEx = new ConnectionException();
try
{
...
}
catch (Exception ex)
{
throw connectionEx;
}
...
}
现在你的用户将会看到异常,即使没有任何异常。
最后一件事是,我建议不要捕获异常只是为了抛出自定义异常。原因是,可能还有其他事情也会引发异常。例如,积极响应处理中的某些内容为空。
根据如何登录方法使用,例如直接在Android活动,我会做这样的事情:
public async Task Login(string username, string password)
{
//TODO: Do parameter check for username and password
try
{
var response = await GetAsync(new Uri(Constants.loginEndpoint + username + "/" + password + "/"));
if (response.IsSuccessStatusCode)
{
// Process the positive response here
}
else
{
var alertDialog = new AlertDialog.Builder(context)
.SetTitle("Failure")
.SetMessage("Request failed.")
.SetPositiveButton("OK", (senderAlert, args) =>
{
Finish();
})
.Create();
alertDialog.Show();
}
}
catch (Exception ex)
{
var alertDialog = new AlertDialog.Builder(context)
.SetTitle("Failure")
.SetMessage("Something went wrong (" + ex.Message +")")
.SetPositiveButton("OK", (senderAlert, args) =>
{
Finish();
})
.Create();
alertDialog.Show();
}
}
感谢您的回答。 1)我通常不用C#编程,这就是为什么我没有遵循上述惯例,所以现在改变aaaall我的代码中的方法仅仅是为了以大写字母开头的方法是毫无意义的。 2)你的建议是对的,我不应该在这里使用string.Empty。 3)字符串作为返回值的目的是能够将指定的消息返回给调用函数。我没有设计和实现服务器API,这就是为什么我想让这个方法足够灵活来处理“消息”的原因。 再次感谢您的回答。 – jkwi
我测试了你的代码,AlertDialog没有显示。相反,在Show()之后引发另一个异常。 – jkwi
好吧,我的不好,这是我抛出异常的代码的另一部分。我使用了@SushiHangover的解决方案,因为AlertDialog是在异步方法的后台线程上创建的,因此您的解决方案无法工作。 – jkwi
异常对象本身不应该是负责显示的消息。您也(可能)试图在后台线程上显示UI警报。 – Jason