带回调的警报
返回Task 的DisplayAlert方法的用途是向用户询问是或否答案的问题。 显然,在用户按下按钮并且警报被取消之前,答案是不可用的,此时真值表示是,错误值表示否。
使用Task 对象的一种方法是使用回调方法。 AlertCallbacks程序演示了这种方法。 它有一个XAML文件,带有一个用于调用警报的Button和一个用于显示某些信息的程序的Label:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="AlertCallbacks.AlertCallbacksPage">
<StackLayout>
<Button Text="Invoke Alert"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Clicked="OnButtonClicked" />
<Label x:Name="label"
Text="Tap button to invoke alert"
FontSize="Large"
HorizontalTextAlignment="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
这是带有Clicked事件处理程序和两个回调方法的代码隐藏文件:
public partial class AlertCallbacksPage : ContentPage
{
bool result;
public AlertCallbacksPage()
{
InitializeComponent();
}
void OnButtonClicked(object sender, EventArgs args)
{
Task<bool> task = DisplayAlert("Simple Alert", "Decide on an option",
"yes or ok", "no or cancel");
task.ContinueWith(AlertDismissedCallback);
label.Text = "Alert is currently displayed";
}
void AlertDismissedCallback(Task<bool> task)
{
result = task.Result;
Device.BeginInvokeOnMainThread(DisplayResultCallback);
}
void DisplayResultCallback()
{
label.Text = String.Format("Alert {0} button was pressed",
result ? "OK" : "Cancel");
}
}
Clicked处理程序调用DisplayAlert,其参数指示标题,问题或语句以及两个按钮的文本。通常,这两个按钮标记为“是”和“否”,或“确定”和“取消”,但您可以在此程序演示中将所需内容放在这些按钮中。
如果将DisplayAlert设计为同步方法,则该方法将返回一个bool,指示用户按下哪个按钮来关闭警报。但是,在警报被取消之前,DisplayAlert将无法返回该值,这意味着在显示警报的整个过程中应用程序将停留在DisplayAlert调用中。根据操作系统处理用户输入事件的方式,在此期间卡在DisplayAlert调用中可能实际上不会阻止用户界面线程的其他事件处理,但UI线程看起来可能有点奇怪。 DisplayAlert调用同时还处理其他事件。
当警报被解除时,DisplayAlert不会返回bool,而是返回一个Task 对象,该对象在将来的某个时间承诺bool结果。要获取该值,AlertCallbacks程序中的OnButtonClicked处理程序将调用Task定义的ContinueWith方法。此方法允许程序指定在解除警报时调用的方法。 Clicked处理程序通过将一些文本设置为Label来结束,然后将控制权返回给操作系统。
然后显示警报:
当然,警报实际上会禁用应用程序的用户界面,但应用程序仍然可以在显示警报时执行某些操作。 例如,程序可能正在使用计时器,该计时器将继续运行。 您可以通过将以下代码添加到AlertCallbacks代码隐藏文件的构造函数来证明这一点:
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
label.Text = DateTime.Now.ToString();
return true;
});
当用户通过点击其中一个按钮来取消警报时,将调用AlertDismissedCallback方法:
void AlertDismissedCallback(Task<bool> task)
{
result = task.Result;
Device.BeginInvokeOnMainThread(DisplayResultCallback);
}
参数是最初从DisplayAlert方法返回的相同Task对象。 但是现在Task对象的Result属性已设置为true或false,具体取决于用户按下哪个按钮来关闭警报。 程序想要显示该值,但不幸的是它不能,因为这个AlertDismissedCallback方法正在Xamarin.Forms创建的辅助线程中运行。 不允许此线程访问程序的任何用户界面对象。 因此,AlertDismissedCallback方法将bool结果保存在字段中并调用Device-
.BeginInvokeOnMainThread带有第二个回调方法。 该回调方法在UI线程中运行:
void DisplayResultCallback()
{
label.Text = String.Format("Alert {0} button was pressed",
result ? "OK" : "Cancel");
}
然后Label显示该文本:
AlertCallbacks程序演示了一种处理异步方法的传统方法,但它有一个明显的缺点:回调太多,在一种情况下,必须使用字段将数据从一个回调传递到另一个回调。