Я пишу приложение для Android в Xamarin, которое заполняет список данными из HttpClient. Есть несколько экранов.
Вот проблема:
Я делаю асинхронный вызов, чтобы получить некоторые данные Json для списка. Я запускаю это право, когда пользователь переходит к действию, которое показывает список. Это отлично работает, если пользователь не уходит. Пользовательский интерфейс реагирует во время запуска сетевого вызова. Большой.
Но если пользователь быстро переходит на другой экран, а затем возвращается обратно до завершения асинхронных вызовов, возникает необработанное исключение без подробностей. Я предполагаю, что происходит то, что httpClient возвращает данные, но возвращает их удаленной активности.
Я пытался использовать токены отмены, поэтому, когда они уходят, я вызываю Cancel для CancelTokenSource. Возможно, я делаю это неправильно, вы должны ждать, пока не получите подтверждение об отмене асинхронного вызова, прежде чем продолжить каким-либо образом?
Как правильно предотвратить эту проблему?
КОД:
во фрагменте:
private async void SwipeRefreshLayout_Refresh(object sender, EventArgs e)
{
_cancelRefreshCall = new CancellationTokenSource();
var swipeRefreshLayout = View.FindViewById<SwipeRefreshLayout>(Resource.Id.swipeRefreshLayout1);
swipeRefreshLayout.Refreshing = true;
_items.Clear();
List<item> items = new List<item>();
try
{
await Task.Run(async () =>
{
try
{
await _itemService.RefreshItems(_cancelRefreshCall.Token);
restaurants = await _itemService.GetLatestItems(_cancelRefreshCall.Token);
}
catch (System.OperationCanceledException ex)
{
}
catch (Exception ex)
{
}
}, _cancelRefreshCall.Token);
}
catch (Exception ex)
{
}
foreach (var item in items)
{
_items.Add(item);
}
swipeRefreshLayout.Refreshing = false;
}
Вот кнопка, чтобы уйти:
private void SubmitItem_Click(object sender, EventArgs e)
{
if (_cancelRefreshCall != null)
{
_cancelRefreshCall.Cancel();
}
// redirect to preference page once done
var fgManager = this.Activity.SupportFragmentManager.BeginTransaction();
var fragment = this.Activity.SupportFragmentManager.FindFragmentByTag(Constants.LeahNutrinoPrefTag);
if (fragment== null)
{
fgManager.Replace(Resource.Id.HomeFrameLayout, new ProfileFragment(), Constants.ProfileTag);
}
else
{
fgManager.Replace(Resource.Id.HomeFrameLayout, fragment, Constants.ProfileTag);
}
fgManager.Commit();
}