处理异步方法的配置更改

时间:2014-07-30 01:00:34

标签: xamarin xamarin.android async-await c#-5.0

我的活动中有一个异步方法。这种异步方法长期运行。异步方法返回后,需要更新UI,并且某些控件引用该活动。 目前,如果在异步任务运行时没有配置更改(如屏幕旋转),一切都能正常工作。但是,如果在运行时发生配置更改,则会抛出异常Activity被销毁并且UI不会更新。从我所做的阅读开始,这似乎是因为异步方法捕获了上下文,然后尝试更新旧的上下文,当然在配置更改后会被破坏。

我的问题是:解决这个问题的最佳方法是什么,或者在最坏的情况下解决这个问题?

3 个答案:

答案 0 :(得分:2)

我个人认为你只有三个选择

  • 您可以永久或暂时禁用轮换,但这是一种不好的做法

永久禁用设置ConfigurationChanges

[Activity(Label = "...", ConfigurationChanges = Android.Content.PM.ConfigChanges.KeyboardHidden | Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]   

在任务正常工作时暂时禁用,您应禁用旋转处理

禁用

this.RequestedOrientation = Android.Content.PM.ScreenOrientation.Nosensor;

使

this.RequestedOrientation = Android.Content.PM.ScreenOrientation.Sensor;
  • 如果您正在使用片段,则可以使用RetainInstance = true防止片段破坏。这可能有用,但我从未测试过。

  • 您可以使用CancelationToken取消任务,然后在OnRestoreInstanceState()重新启动 以下是取消任务的示例

    { CancellationTokenSource cts; ... // If a download process is already underway, cancel it. if (cts != null) { cts.Cancel(); }
    // Now set cts to cancel the current process if the button is chosen again. CancellationTokenSource newCTS = new CancellationTokenSource(); cts = newCTS;
    try { //Send cts.Token to carry the message if there is a cancellation request. await AccessTheWebAsync(cts.Token); } // Catch cancellations separately. catch (OperationCanceledException) { ResultsTextBox.Text += "\r\nDownloads canceled.\r\n"; } catch (Exception) { ResultsTextBox.Text += "\r\nDownloads failed.\r\n"; } // When the process is complete, signal that another process can proceed. 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();
    ...
}

答案 1 :(得分:0)

你可以做很多事情,但请不要去禁用手机转动屏幕的能力 - 这只会忽略你的用户。

在高级别你必须做两件事:

  1. 确保异步任务继续运行,如果活动中断,则不会重新启动。
  2. 您可以通过将任务移入应用程序类或(清理器)到setRetainInstance设置为true的无头片段来解决此问题。

    1. 在活动的onDestroy方法中,将其从异步任务中删除,在onCreate任务中将活动提供给异步任务(如果存在)。
    2. 这是阻止异步任务调用旧上下文的原因,可以通过异步任务上的简单java setter来完成。如果活动当前未连接,请不要忘记将结果缓存在任务中。

答案 2 :(得分:0)

最后我最终做的是将异步任务封装在另一个类中,该类持有对当前活动的引用,该类实现了接口,定义了一个处理异步响应并更新UI的方法。

活动保存了封装的异步任务的静态变量,如果它在配置更改期间运行,则封装的异步对活动的任务引用已更新为新活动。