对于我在学习xamarin期间的第一个项目,我制作了一个简单的应用程序,用户可以创建一个笔记并添加闹钟时间来安排本地通知。 当app从后台恢复时,我遇到了问题。
重点。
注意型号:
public class Note
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[MaxLength(255)]
public string Title { get; set; }
[MaxLength(255)]
public string Content { get; set; }
public DateTime TimeCreate { get; set; }
public DateTime AlarmTime { get; set; }
public bool AlarmTimeActive { get; set; }
}
在主页面中有备注列表。每个音符都有一个开关按钮,用户可以开/关时间报警。 如果用户尝试打开警报,则功能检查是否已经过了调度时间。如果没有,那么切换保持在关闭位置和应用程序显示信息。在其他情况下,函数更新将数据库中的值更改为" true"。
XAML
<local:ButtonActiveSwitcher Toggled="Switch_Toggled" IsToggled="{Binding AlarmTimeActive}" Active="{Binding .}" />
功能&#34; Switch_Toggled&#34;
private void Switch_Toggled(object sender, ToggledEventArgs e)
{
var switchBtn = sender as Switch;
var item = ((ButtonActiveSwitcher)sender).Active;
if (item != null)
{
if (item.AlarmTime < DateTime.Now)
{
if (_nooLoopTime.AddSeconds(2) < DateTime.Now) //Prevent double display alert
{
DisplayAlert("ALERT", "Time gone", "OK");
_nooLoopTime = DateTime.Now;
}
switchBtn.IsToggled = false;
return;
}
DataBaseService.updateRecord(item);
}
}
当用户点击切换台时,此功能正常工作。
下一点。
在函数OnAppearing
app的 MainPage.cs 中解雇函数DataBaseService.checkNoteAlarmTimeActive();
。在此功能应用中,在备注中选中AlarmTime
。如果AlarmTimeActive
处于有效状态但计划时间已经过去,则将AlarmTimeActive
更改为&#34; false&#34;。
第一个应用程序检查数据库中的Notes并更新它们,下一个函数loadNotes()
从数据库获取Notes并填充列表。
因此,应用程序从数据库中获取数据库中的第一个更新记录。
MainPage.cs
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainPage : ContentPage
{
private Sorting _sorting;
private int _sortOption;
private bool _activeSwitcherState;
private DateTime _nooLoopTime;
public MainPage(int noteid)
{
DataBaseService.CreateTables();
this._sorting = new Sorting();
InitializeComponent();
this.AddPickerItems();
if (noteid != 0)
{
this.loadNoteView(noteid);
}
}
protected async override void OnAppearing()
{
await DataBaseService.checkNoteAlarmTimeActive();
this.loadNotes();
base.OnAppearing();
}
/// <summary>
/// Generate list of notes basic on current sorting option and active switcher
/// </summary>
private async void loadNotes()
{
listNotes.ItemsSource = await _sorting.sortNotes(_sortOption, _activeSwitcherState);
}
}
这是我的问题。
例如:一个音符有AlarmTimeActive
&#34; true&#34;用户点击了#34; Home&#34;按钮,应用程序转到后台。稍后当计划闹钟时间结束时,用户通过点击应用程序切换器按钮下的列表中的应用程序将应用程序置于前台。由于某种原因,应用程序首先显示警报&#34;时间消失&#34;后者(我认为)做功能OnAppearing()
。最后在主页面中,我有一个包含更新记录的Notes列表,但为什么app会先显示此警报?
但是这个问题在其他三个案例中并没有出现 用户在App Switcher列表中杀死应用程序并再次打开应用程序列表中的点击图标 用户退出应用程序轻触后退按钮 用户通过点按通知恢复应用。
那么,如果用户从App Switcher列表中恢复应用,为什么会显示此警报,但在其他情况下却没有?
我希望我的描述清楚。 请向我解释为什么会发生以及如何解决它。
答案 0 :(得分:1)
除了事件处理程序之外,尽量避免使用async void
。 OnAppearing
不是事件处理程序。但它是否在实际的Appearing
事件之前被调用,这使您有机会使用实际的事件处理程序订阅它,这将允许您正确使用async / await。
protected override void OnAppearing() {
this.Appearing += Page_Appearing;
base.OnAppearing();
}
private async void Page_Appearing(object sender, EventArgs e) {
//...call async code here
await DataBaseService.checkNoteAlarmTimeActive();
var notes = await loadNotes();
listNotes.ItemsSource = notes;
//unsubscribing from the event (optional but advised)
this.Appearing -= Page_Appearing;
}
/// <summary>
/// Generate list of notes basic on current sorting option and active switcher
/// </summary>
private Task<IEnumerable<Note>> loadNotes()
{
return _sorting.sortNotes(_sortOption, _activeSwitcherState);
}
我可能会猜到这段代码......
if (noteid != 0)
{
this.loadNoteView(noteid);
}
构造函数中调用的也应该重构到事件处理程序中。