昨今のネイティブクライアントアプリで、 HTTP 通信を行わないものはないと言っても過言ではないくらい、アプリ開発の基本中の基本だと思います。きっと、開発を行う中で HTTP 通信の前後に色々な処理を挟んでみたいという気持ちが湧いてくるのではないでしょうか。たとえば以下のような話です。

  1. リクエストの内容をログ出力したい
  2. 電波状況が悪いときはリクエストを走らせないようにしたい
  3. 通信中はネットワークアクティビティインジケータを走らせたい

 そんなときに System.Net.Http.DelegatingHandler はとても便利な代物です。公式のドキュメントはこちら: https://msdn.microsoft.com/ja-jp/library/system.net.http.delegatinghandler(v=vs.110).aspx

1. HTTP リクエストのログ出力

 たとえば、Http リクエストの内容をログ出力したいとすれば、以下のような簡単な DelegatingHandler のサブクラスを作ってあげるとよいでしょう。

 実用的には Console.WriteLine をクリティカルセクションに配置したほうが良いかもしれませんが、ひとまずこのような単純なコードでリクエストの手前に処理を挟むことができました。使い方は、単純にこれを System.Net.Http.HttpClient のコンストラクタに渡すだけです。これで全てのリクエストの内容がログ出力されます。

2. 圏外時にリクエストを送らない

Reachability を使えば簡単です。

3. 通信中にネットワークアクティビティインジケータを回す

 ネットワークアクティビティインジケータの管理、非常にめんどうですよね。通信が同時に複数走るのはザラなので、そのあたりを考慮する必要があると思います。だいたい皆さん同じような実装をすると思うのですが、今走っている通信の数が正であれば、インジケータを回しっぱなしにして、0になったら止めるみたいなカウンターを作るのではないかなと思います。ひとまずステップをわけて実装を見ていきます。

3.1. NetworkActivityIndicator の抽象化

 ネットワークアクティビティマネージャは基本的に ON/OFF のインターフェースさえ持っていれば十分でしょう。それぞれActivate(), Inactivate() という名前のメソッドとします。実装クラスは、UIApplication インスタンスを外から受け取り、Activate(), Inactivate() のタイミングで NetworkActivityIndicatorVisible の値に true, false をぶち込んであげれば良いという話になります。

3.2. 走っているリクエストをカウントするクラスの作成

 同時に走っているリクエストが1つ以上ある場合に IIndicatorActivate() を呼び出し、通信が走っていない状態になるとき Inactivate() を呼び出す簡単なカウンタークラスを作りましょう。

 このカウンタークラスは、通信開始時には Attach()、 終了時には Detach() を呼ぶ簡単なインターフェースを持つことになるでしょう。それぞれインターフェースと実装コードは以下のようになると思います。

3.3. DelegatingHandler の実装

 準備ができたので、今まで作ったものを利用してネットワークアクティビティインジケータを通信が走っているときにクルクルまわす DelegatingHandler を実装しましょう。以下のようになります。

 コード全体を GitHub で公開しているので使いたい方はどうぞ。MITライセンスです。 Xamarin.iOSに依存するパッケージの nuget への放流方法イマイチよくわからんので有識者の方、教えていただけると嬉しいです

  • Repository: https://github.com/pawotter/NetworkActivityManager

3.4. Swift での実現方法

 URLSessionラップして、自分で HttpClient 作ればできるよ。実装はだいたい同じ。実装的にもパフォーマンス的にも改善の余地があるコードですが、わかりやすく伝えるとするならば以下のような実装コードになる気がします。

5. おわりに

DelegatingHandler ベンリすぎワロタ。あとこれを使うとリトライ処理とかも挟めてとってもベンリ&ベンリです。良いですね〜。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です