gpt4 book ai didi

c# - TaskCompletionSource 和 dismiss 导致多个自定义警报对话框没有出现

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:13:48 27 4
gpt4 key购买 nike

我遇到了与 TaskCompletionSource 对象和警报的 Dismiss 函数相关的问题。 IOS版本的应用中没有出现这个问题

当应用程序发送通知时,当用户激活应用程序时,将显示两个具有工作功能的警报:

  1. 身份验证
  2. 填写一个值。

但是,当我进入应用程序时,我只能看到身份验证(因为此警报首先在应用程序中调用),而第二个警报永远不会出现。我已经尝试覆盖 Dismiss 函数并将 TaskCompletionSource 对象结果设置为 null,但这会导致相同的警报在应用程序崩溃前出现 X 次。有没有办法重复 TaskCompletionSource 对象,以便我可以看到所有警报?或者我需要对 Dismiss 函数进行什么样的修改,以便在显示所有警报后完成 TaskCompletionSource?

Android fragment 示例代码:

public static readonly int AlertWidth = Device.Idiom == TargetIdiom.Phone ? 270 : 320;

class AlertDialogFragment : DialogFragment
{
public string Title;
public string Body;
public View Content;
public List<AlertButton> Buttons;
public TaskCompletionSource<object> tsc;


public Dialog AndroidCustomAlert(Activity activ)
{
Android.Views.LayoutInflater inflater = Android.Views.LayoutInflater.From(activ);
Android.Views.View view = inflater.Inflate(Resource.Layout.AlertDialogLayout, null);

AlertDialog.Builder builder = new AlertDialog.Builder(activ);
builder.SetView(view);
Android.Widget.TextView title = view.FindViewById<Android.Widget.TextView>(Resource.Id.Login);
title.Text = Title;

Android.Widget.TextView body = view.FindViewById<Android.Widget.TextView>(Resource.Id.pincodeText);
body.Text = Body;
body.MovementMethod = new Android.Text.Method.ScrollingMovementMethod();

Android.Widget.EditText pincode = view.FindViewById<Android.Widget.EditText>(Resource.Id.pincodeEditText);
Android.Widget.Button btnPositive = view.FindViewById<Android.Widget.Button>(Resource.Id.btnLoginLL);
Android.Widget.Button btnNegative = view.FindViewById<Android.Widget.Button>(Resource.Id.btnClearLL);
Android.Widget.Button btnNeutral = view.FindViewById<Android.Widget.Button>(Resource.Id.btnNeutral);

if (Title.Contains("Time"))
{
Android.Views.View secondView = inflater.Inflate(Resource.Layout.TimePickerLayout, null);
builder.SetView(secondView);

btnPositive = secondView.FindViewById<Android.Widget.Button>(Resource.Id.btnLoginLL);
btnNegative = secondView.FindViewById<Android.Widget.Button>(Resource.Id.btnClearLL);
var tp = secondView.FindViewById<Android.Widget.TimePicker>(Resource.Id.timePicker1);
tp.SetIs24HourView((Java.Lang.Boolean)true);
//Positive button feedback
btnPositive.Text = Buttons.Last().Text;
btnPositive.Click += delegate
{
var car = (Xamarin.Forms.TimePicker)Content;
var ts = new TimeSpan(tp.Hour, tp.Minute, 0);
car.Time = ts;

CommandsForButtons(Buttons.Last());
};

//Negative button feedback
btnNegative.Text = Buttons.First().Text;
btnNegative.Click += delegate
{

CommandsForButtons(Buttons.First());
};
}
else if (Title.Contains("How are you"))
{
btnPositive.Visibility = Android.Views.ViewStates.Gone;
btnNegative.Visibility = Android.Views.ViewStates.Gone;
btnNeutral.Visibility = Android.Views.ViewStates.Visible;
pincode.Visibility = Android.Views.ViewStates.Gone;

var happySlider = view.FindViewById<Android.Widget.SeekBar>(Resource.Id.happinessSlider);
happySlider.SetProgress(5, false);
happySlider.Visibility = Android.Views.ViewStates.Visible;
btnNeutral.Text = Buttons.First().Text;
btnNeutral.Click += delegate
{
var car = (StackLayout)Content;

var layoutView = (Xamarin.Forms.AbsoluteLayout)car.Children[1];
var slider = (Slider)layoutView.Children[1];

var totalHappyValue = happySlider.Progress / 10;
slider.Value = totalHappyValue;

CommandsForButtons(Buttons.First());
};
}
else
{

//Checks if there are no buttons, and if there aren't any, creates a neutral one
if (Buttons == null || Buttons.Count == 0)
{
btnPositive.Visibility = Android.Views.ViewStates.Gone;
btnNegative.Visibility = Android.Views.ViewStates.Gone;
btnNeutral.Visibility = Android.Views.ViewStates.Visible;
pincode.Visibility = Android.Views.ViewStates.Gone;

Buttons = new List<AlertButton> {
new AlertButton {
Text = "Oké",
IsPreferred = true,
Action = () => false
}
};
btnNeutral.Text = Buttons.First().Text;
btnNeutral.Click += delegate
{

CommandsForButtons(Buttons.First());
};
}

if (Content == null)
{
pincode.Visibility = Android.Views.ViewStates.Gone;
}

//Positive button feedback
btnPositive.Text = Buttons.Last().Text;
btnPositive.Click += delegate
{
var test = (StackLayout)Content;

if (test != null)
{
var car = (Entry)test.Children[0];
car.Text = pincode.Text;
}

CommandsForButtons(Buttons.Last());
};

//Negative button feedback
btnNegative.Text = Buttons.First().Text;
btnNegative.Click += delegate
{

CommandsForButtons(Buttons.First());
};
}
return builder.Create();
}

public void CommandsForButtons(AlertButton button)
{
Func<Task> dismiss = null;
var command = new Command(async () =>
{
var ab = button;
var cont = true;
if (ab.Action != null)
cont = ab.Action();
if (ab.ActionAsync != null)
{
cont = cont && await ab.ActionAsync();
}
if (!cont)
{
await dismiss();
}
});

dismiss = async () =>
{
dismiss = async () => { };
await Task.Run(() =>
{
Dismiss();
tsc.SetResult(null);
});

Log.Debug("TSC", tsc.Task.Status.ToString());

};

command.Execute(this);
}

public override Dialog OnCreateDialog(Bundle savedInstanceState)
{
var test = AndroidCustomAlert(Activity);
test.SetCanceledOnTouchOutside(false);
return test;
}

public override void Dismiss()
{
base.Dismiss();

}
}

public async Task Show(string title, string body, View content, List<AlertButton> buttons)
{

var tcs = new TaskCompletionSource<object>();

var adf = new AlertDialogFragment
{
Title = title,
Body = body,
Content = content,
Buttons = buttons,
tsc = tcs
};
var FragmentManager = ((Activity)Forms.Context).FragmentManager;
FragmentTransaction ft = FragmentManager.BeginTransaction();

//Remove fragment else it will crash as it is already added to backstack
Fragment prev = FragmentManager.FindFragmentByTag("alert");
if (prev != null)
{
ft.Remove(prev);
}

ft.AddToBackStack(null);
adf.Show(ft, "alert");
await tcs.Task;
}

方法:

await Authentication();
await UserCheck();

和IOS代码:

public static readonly int AlertWidth = Device.Idiom == TargetIdiom.Phone ? 270 : 320;

public async Task Show(string title, string body, View content, List<AlertButton> buttons)
{
if (buttons == null || buttons.Count == 0)
{
buttons = new List<AlertButton> {
new AlertButton {
Text = "Oké",
IsPreferred = true,
Action = () => false
}
};
}

Func<Task> dismiss = null;

var captionSize = (double)StyleKit.PhoneDarkLabelStyles.Caption.Setters.First(s => s.Property == Label.FontSizeProperty).Value;
var titleSize = (double)StyleKit.PhoneDarkLabelStyles.Title.Setters.First(s => s.Property == Label.FontSizeProperty).Value;

var top = new StackLayout {
Padding = new Thickness(15, 20, 15, 20),
Spacing = 3,
Children = {
new Label {
Text = title,
Style = StyleKit.PhoneDarkLabelStyles.Title,
FontSize = Math.Max(16, titleSize),
HorizontalTextAlignment = TextAlignment.Center
},
new Label {
Text = body,
Style = StyleKit.PhoneDarkLabelStyles.Body,
//FontSize = ,
FontSize = Math.Max(14, captionSize),
HorizontalTextAlignment = TextAlignment.Center
} ,
new ContentView {
Padding = new Thickness(0,5,0,-10),
VerticalOptions = LayoutOptions.EndAndExpand,
Content = content
}
}
};

var buttonViews = buttons.Select(ab => new Button {
FontSize = Math.Max(16, titleSize),
Text = ab.Text,
FontAttributes = ab.IsPreferred ? FontAttributes.Bold : FontAttributes.None,
TextColor = ab.IsDestructive ? Color.Red : Color.Default,
Command = new Command(async () => {
var cont = true;
if (ab.Action != null)
cont = ab.Action();
if (ab.ActionAsync != null)
cont = cont && await ab.ActionAsync();
if (!cont)
await dismiss();
})
}).ToList();

var grid = new Grid {
RowDefinitions = {
new RowDefinition { Height = GridLength.Auto },
new RowDefinition { Height = GridLength.Auto }
},
ColumnSpacing = 0,
RowSpacing = 0
};
buttons.ForEach(button => {
grid.ColumnDefinitions.Add(
new ColumnDefinition {
Width = AlertWidth / buttonViews.Count
}
);
});

for (int i = 0; i < buttonViews.Count; i++)
{
grid.Children.Add(new BorderView {
BorderColor = Color.FromRgba(0,0,0,0.2),
Thickness = new Thickness(0, 1, (i + 1 < buttonViews.Count) ? 1 : 0, 0)
}, i, 1);
grid.Children.Add(buttonViews[i], i, 1);
}
grid.Children.Add(top, 0, buttons.Count, 0, 1);

var box = new Frame {
WidthRequest = AlertWidth,
BackgroundColor = Color.FromRgba(1,1,1,0.96),
Padding = 0,
Content = grid
};
var outer = new AbsoluteLayout {
BackgroundColor = Color.FromRgba(0,0,0,0.65),
Opacity = 0,
Children = { box }
};
AbsoluteLayout.SetLayoutFlags(box, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(box,
new Rectangle(0.5, 0.5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));

var page = new ContentPage {
Content = /* new ScrollView { Content = */ outer // }
};

var tcs = new TaskCompletionSource<object>();

var topVC = UIApplication.SharedApplication.KeyWindow.RootViewController;
while (topVC.PresentedViewController != null) {
topVC = topVC.PresentedViewController;
}

var vc = page.CreateViewController();
topVC.Add(vc.View);
var innerView = vc.View.Subviews[0].Subviews[0];
vc.View.RemoveFromSuperview();

dismiss = async () => {
dismiss = async () => {};
await outer.FadeTo(0, 50);
innerView.RemoveFromSuperview();
tcs.SetResult(null);
};

topVC.Add(innerView);

var kbh = new KeyboardHelper();
kbh.KeyboardChanged += async (sender, e) => {
await box.TranslateTo(0, e.Visible ? (-e.Height / 2f) : 0, 100, Easing.CubicInOut);
};

await outer.FadeTo(1, 100);

await tcs.Task;
}

最佳答案

这看起来像是线程之间的和/或问题,或者根本没有设置任务完成。

在你的IOS版本中

     dismiss = async () => {
dismiss = async () => {};
await outer.FadeTo(0, 50);
innerView.RemoveFromSuperview();
tcs.SetResult(null);
};

android版本中没有匹配的tcs.SetResult(null);语句。

另外值得注意的是异步调用,因为等待调用 SetResult 将在没有它的情况下阻塞主线程。

关于c# - TaskCompletionSource 和 dismiss 导致多个自定义警报对话框没有出现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44228853/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com