Xamarin 处理异步方法的配置更改
我有一个活动,其中包含一个异步方法。此异步方法正在长时间运行。异步方法返回后,需要更新UI,并且一些控件引用活动。 目前,如果在异步任务运行时未进行配置更改(如屏幕旋转),则一切正常。但是,如果在运行时发生配置更改,则会引发异常活动并不会更新UI。从我阅读的内容来看,这似乎是因为异步方法捕获上下文,然后尝试更新旧上下文,而旧上下文在配置更改后当然会被破坏Xamarin 处理异步方法的配置更改,xamarin,xamarin.android,async-await,c#-5.0,Xamarin,Xamarin.android,Async Await,C# 5.0,我有一个活动,其中包含一个异步方法。此异步方法正在长时间运行。异步方法返回后,需要更新UI,并且一些控件引用活动。 目前,如果在异步任务运行时未进行配置更改(如屏幕旋转),则一切正常。但是,如果在运行时发生配置更改,则会引发异常活动并不会更新UI。从我阅读的内容来看,这似乎是因为异步方法捕获上下文,然后尝试更新旧上下文,而旧上下文在配置更改后当然会被破坏 我的问题是:解决这个问题的最好方法是什么,或者在最坏的情况下解决它?我个人认为你只有三个选择 您可以永久或临时禁用旋转,但这是一种不好的做法
我的问题是:解决这个问题的最好方法是什么,或者在最坏的情况下解决它?我个人认为你只有三个选择
- 您可以永久或临时禁用旋转,但这是一种不好的做法
[Activity(Label = "...", ConfigurationChanges = Android.Content.PM.ConfigChanges.KeyboardHidden | Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
要在任务工作时临时禁用它,应禁用旋转处理
禁用
使能
- 如果您使用的是fragment,则可以使用
防止碎片销毁。这可能有效,但我从未测试过RetainInstance=true
- 您可以使用
取消任务,然后在CancelationToken
下面是如何取消任务的示例OnRestoreInstanceState()
{ 取消源cts; ... //如果下载过程已在进行中,请取消它。 如果(cts!=null) { cts.Cancel(); }
//现在,如果再次选择按钮,则设置cts以取消当前进程。 CancellationTokenSource newCTS=新的CancellationTokenSource(); cts=新cts;
尝试 { //如果有取消请求,则发送cts.Token以承载消息。 等待访问WebAsync(cts.Token); } //单独捕获取消。 捕获(操作取消异常) { ResultsTextBox.Text+=“\r\n已取消下载。\r\n”; } 捕获(例外) { ResultsTextBox.Text+=“\r\n下载失败。\r\n”; } //当流程完成时,发出另一流程可以继续的信号。 if(cts==newCTS) cts=null; }
async Task AccessTheWebAsync(CancellationToken ct)
{
...
// Retrieve the website contents from the HttpResponseMessage.
byte[] urlContents = await response.Content.ReadAsByteArrayAsync();
// Check for cancellations before displaying information about the
// latest site.
ct.ThrowIfCancellationRequested();
...
}
你可以做很多事情,但请不要去禁用手机的屏幕切换功能——这只会忽略你的用户 在高水平上,你必须做两件事:
这就是阻止异步任务调用旧上下文的原因,可以使用异步任务上的简单java setter来完成。如果活动当前未连接,请不要忘记在任务中缓存结果。最后,我将异步任务封装在另一个类中,该类包含对当前活动的引用,该类实现了一个接口,该接口定义了一个处理异步响应和更新UI的方法
该活动包含封装异步任务的静态变量,如果它在配置更改期间运行,则封装异步任务对该活动的引用将更新为新活动。感谢您的建议。我同意禁用旋转是非常糟糕的,我不会这么做。异步任务在轮换时不会停止,所以这不是问题。看起来带保留状态的片段是最干净的解决方案。谢谢你的建议。同意禁用旋转是个糟糕的主意,所以我不会这么做。似乎带有保留状态的片段是最干净的解决方案。我没有考虑过取消该任务,但这也可以工作,但这意味着该任务可能需要重新启动。考虑到我们是C#举办一些活动也可能奏效,但这似乎很混乱。我会将此作为答案,因为它提供了最多的建议和示例。
this.RequestedOrientation = Android.Content.PM.ScreenOrientation.Sensor;
async Task AccessTheWebAsync(CancellationToken ct)
{
...
// Retrieve the website contents from the HttpResponseMessage.
byte[] urlContents = await response.Content.ReadAsByteArrayAsync();
// Check for cancellations before displaying information about the
// latest site.
ct.ThrowIfCancellationRequested();
...
}