带回调的警报
返回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来结束,然后将控制权返回给操作系统。
然后显示警报:
第二十章:异步和文件I/O.(三)
当然,警报实际上会禁用应用程序的用户界面,但应用程序仍然可以在显示警报时执行某些操作。 例如,程序可能正在使用计时器,该计时器将继续运行。 您可以通过将以下代码添加到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显示该文本:
第二十章:异步和文件I/O.(三)
AlertCallbacks程序演示了一种处理异步方法的传统方法,但它有一个明显的缺点:回调太多,在一种情况下,必须使用字段将数据从一个回调传递到另一个回调。

相关文章: