2017-08-11 16 views
0

XamarinにHttpClientのデータでリストを埋め込むアンドロイドアプリを作成しています。複数の画面があります。私は、非同期呼び出しがリストについては、いくつかのJSONデータを取りに行くために作るAndroid、非同期/アクティビティネガティブ処理後にスロー例外が発生する

は、ここで問題です。ユーザーがリストを表示しているアクティビティに移動すると、この権利が発生します。これは、ユーザーが離れて移動しない場合、正常に動作します。ネットワークコールが起動している間、UIは応答します。すばらしいです。

しかし、ユーザーが別の画面にすばやく移動して、非同期呼び出しが完了する前に戻ると、未処理の例外が詳細なしでスローされます。何が起こっているのかは、httpClientがデータを戻していることを前提としていますが、廃棄されたアクティビティーに戻しています。

キャンセルトークンを使用しようとしました。そのため、離れたところを移動すると、cancellationTokenSourceでキャンセルを呼び出します。私はそれを間違ってやっているかもしれませんが、何とか続行する前に非同期呼び出しがキャンセルされたという確認を受けるまで待つべきですか?

この問題を防ぐ適切な方法は何ですか?

CODE:フラグメントで

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(); 
    } 
+1

は、あなたがしようとしている何の問題のいくつかのコードサンプルを供給することはできますか? –

+0

完了しました、ごめんなさい。 – GMorini

答えて

0

あなたが_ cancelRefreshCallフィールドの上に閉じているということだろう?新しい値を割り当てるたびに、実行中のタスクのクロージャは、キャンセルされていない新規のCancellationTokenSourceを指します。

あなたは代わりに以下のコードを試すことができます。

private async void SwipeRefreshLayout_Refresh(object sender, EventArgs e) 
{ 
    _cancelRefreshCall?.Cancel(); 
    _cancelRefreshCall = new CancellationTokenSource(); 
    var token = _cancelRefreshCall.Token; 
    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(token); 
       restaurants = await _itemService.GetLatestItems(token); 
      } 
      catch (System.OperationCanceledException ex) 
      { 
      } 
      catch (Exception ex) 
      { 

      } 
     }, token); 
    } 
    catch (Exception ex) 
    { 

    } 

    foreach (var item in items) 
    { 
     _items.Add(item); 
    } 

    swipeRefreshLayout.Refreshing = false; 
+0

私はこれを試してみます。私は一時的な解決策を実装しました。ナビゲートするボタンは、クリックされるとトークンソースを取り消します。私はそれがOperationCanceledExceptionをスローすることを知っているので、私はそれをキャッチし、catchブロックで私は遠ざかります。例外が捕捉されるまでには時間がかかります。つまり、タスクがキャンセルされたことを確認するまで、ユーザーは他の画面にナビゲートされません。だから、スクリーンを読み込むのに時間がかかるように見えますが、私たちはタスクがキャンセルされるのを待っています。基になるキャンセルされたメソッドはsendAsyncです。なぜそんなに遅い? – GMorini

+0

これはアドロイドサービスですか?また、キャンセルトークンがある前にこの問題が発生していたので、私はその問題を懐疑的に思っています。私はあなたの解決策を試みます。 – GMorini