WebService から情報を取得するアプリケーションの作成 (2)
それでは実際に Rx を利用した Windows Phone アプリケーションでの Web アクセス処理について見ていきましょう。
Web アクセスプログラミングのキホン
Windows Phone アプリケーションではデスクトップ向けアプリケーションと同様に WebClient クラスや WebRequest / WebResponse クラスを使用して Web 上のリソースにアクセスする事ができます。
但し、ベースとなっている Silverlight と同様に、同期的なアクセスは出来ず全て非同期通信となります。
なお、 Silverlight では(完全信頼のアプリケーションを除いて)クロスドメインアクセスが出来ませんが、 Windows Phone アプリケーションではクロスドメインの制約はなく、基本的に全ての Web リソースへのアクセスが可能です。(接続先の Web リソース側で個別に制限を設けている場合を除きます)
AsynchronousExtensions を活用する
AsynchronousExtensions には、非同期で WebClient や WebRequest / WebResponse を使用するのに便利な拡張メソッドが数多く定義されています。
そのうちのいくつかを紹介しておきます。
WebClient
- IObservable
DownloadStringObservableAsync(string address) - IObservable
DownloadStringObservableAsync(Uri address) - IObservable
DownloadStringObservableAsync(Uri address, IProgress progressReporter)
URI を指定して Web リソースを文字列で取得します。
取得した結果は長さ 1 の Observable
第二引数に progressReporter を指定すると、ダウンロード進捗状況の捕捉が可能になります。(本記事では使用しませんが。。。)
- IObservable
UploadStringObservableAsync(string address, string data, string method = null) - IObservable
UploadStringObservableAsync(Uri address, string data, string method = null) - IObservable
UploadStringObservableAsync(Uri address, string data, IProgress progressReporter, string method = null)
URI を指定して文字列データを送信します。
送信結果は DownloadStringAsync と同じ様に長さ 1 の Observable
WebRequest
- IObservable
DownloadStringAsync() - IObservable
DownloadStringAsync(Encoding encoding) - IObservable
DownloadStringAsync(IProgress progressReporter) - IObservable
DownloadStringAsync(Encoding encoding, IProgress progressReporter)
Web リソースを文字列で取得します。
取得した結果は WebClient の DownloadStringAsync と同様に長さ 1 の Observable
progressReporter を指定すると、ダウンロード進捗状況の捕捉が可能になります、
- IObservable
DownloadStringLineAsync() - IObservable
DownloadStringLineAsync(Encoding encoding)
Web リソースを文字列で取得します。
DownloadString と違い、取得した結果を 1 行ずつ返却します。従って、返却される IObservable
- IObservable
DownloadDataAsync() - IObservable
DownloadDataAsync(IProgress progressReporter)
Web リソースをバイト列データで取得します。
取得した結果は長さ 1 の Observable
- IObservable
GetResponseObservableAsync() - IObservable
GetResponseObservableAsync() (※ HttpWebRequest の拡張メソッド)
WebReponse を直接制御したい場合は長さ 1 の IObservable
- IObservable
UploadStringAsync(string data) - IObservable
UploadStringAsync(string data, Encoding encoding) - IObservable
UploadStringAsync(string data, IProgress progressReporter) - IObservable
UploadStringAsync(string data, Encoding encoding, IProgress progressReporter)
文字列データを送信します。
送信結果は長さ 1 の Observable
- IObservable
UploadValuesAsync(IDictionary parameters) - IObservable
UploadValuesAsync(IDictionary parameters, Encoding encoding) - IObservable
UploadValuesAsync(IDictionary parameters, IProgress progressReporter) - IObservable
UploadValuesAsync(IDictionary parameters, Encoding encoding, IProgress progressReporter)
キーと値のセットを送信します。
送信結果は長さ 1 の Observable
- IObservable
UploadDataAsync(byte[] data) - IObservable
UploadDataAsync(byte[] data, IProgress progressReporter, int chunkSize = 65536)
バイト列データを送信します。
送信結果は長さ 1 の Observable
エラー対策
Windows Phone に限らず、携帯端末の通信は常に接続されている事が保証されないため、通信処理に対するエラー対策は必須と言えます。
非同期処理でのエラーハンドリングはなかなか面倒なものですが、 Rx ではこの点のサポートもされており、処理メソッドチェーンの一部としてエラー処理を記述する事ができます。
リトライ処理 (Retry)
- Retry()
- Retry(int retryCount)
メソッドチェーンの中で Retry を使用すると、前段の処理で発生した例外を捕捉して処理を再実行する事ができます。
「通信処理でタイムアウトが発生した場合に一定回数リトライを行う」と云った処理を非常に簡潔に書く事が可能です。
Retry メソッドの戻り値は IObservable
例外捕捉処理 (Catch)
- Catch()
- Catch(IObservable
second) - Catch(Func
> handler)
メソッドチェーンの中で Catch を使用すると、前段の処理で例外が発生した場合に該当の例外を捕捉して後続の処理を続ける事ができます。
メソッドの引数として後続に流すダミー値を指定可能なため、リトライしても改善の見込みがない様な例外(対象のリソースが見つからない等) が発生した場合等に有用です。
タイムアウト処理 (Timeout)
- Timeout(DateTimeOffset dueTime)
- Timeout(TimeSpan dueTime)
- Timeout(DateTimeOffset dueTime, IScheduler scheduler)
- Timeout(DateTimeOffset dueTime, IObservable
other) - Timeout(TimeSpan dueTime, IScheduler scheduler)
- Timeout(TimeSpan dueTime, IObservable
other) - Timeout(DateTimeOffset dueTime, IObservable
other, IScheduler scheduler) - Timeout(TimeSpan dueTime, IObservable
other, IScheduler scheduler)
前段の処理を一定時間で強制的に打ち切りたい場合、 Timeout メソッドが利用できます。
特に Windows Phone の Web アクセスはタイムアウトの時間を設定できないため、最悪接続先のサーバのタイムアウトまで永遠に待ってしまう恐れがあります。そのため、この Timeout メソッドはとても有用です。
例外の捕捉
メソッドチェーンの途中で例外を捕捉する場合は前述の各メソッドを利用できますが、 Subscribe メソッドの OnException パラメータを使用する事でメソッドチェーンの終端で捕捉する事も可能です。
但しこの場合、例外が発生した時点でメソッドチェーン内の後続処理は全て Abort されるので注意が必要です。