この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
非同期通信
今回は非同期通信の処理を比較してみます。外部ライブラリ等を使わずに素手で殴りあってみます。
目標
「指定したURLのコンテンツを非同期通信にて取得」してLoggerに表示することが目標です
iOS7の場合
iOS7は、NSURLSessionTask クラスを利用します。
詳しくはCMの【iOSハンター(HR.2、武器:太刀)】平井祐樹のエントリから一部借用します。
iOS7において、非同期通を行い、指定したURLからコンテンツを取得するコードは次の通りです。
NSURLSession *session = [NSURLSession sharedSession];
// URL
NSURL *url = [NSURL URLWithString:@"https://classmethod.jp/"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 非同期処理のタスク
NSURLSessionTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
// 通信が異常終了したときの処理
return;
}
// 通信が正に常終了したときの処理
NSLog(@"data : %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}];
// 通信開始
[task resume];
これだけで、指定したURLから非同期でコンテンツを取得することができるようです
Androidの場合
Androidは非同期通信を行う場合は、いくつか方法があると思いますが、今回はAsyncTaskLoaderとDefaultHttpClientを利用した通信手法を実装してみます
AsyncTaskLoaderの使い方は、こちらを参照してください
非同期通信を行うAsyncTaskLoaderクラスは以下のとおり
package jp.classmethod.android.sampleasyncapp;
import android.content.AsyncTaskLoader;
import android.content.Context;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
/**
* ネットワーク通信のためのAsyncTaskLoader
* Created by komuro on 2013/09/18.
*/
public class NetworkAsyncTaskLoader extends AsyncTaskLoader<String> {
private HttpClient httpClient;
private String url;
/**
* Constructor
* @param context
*/
public NetworkAsyncTaskLoader(Context context, String url) {
super(context);
this.url = url;
forceLoad();
}
@Override
public String loadInBackground() {
httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
return httpClient.execute(httpGet, new ResponseHandler<String>() {
@Override
public String handleResponse(HttpResponse httpResponse) throws ClientProtocolException, IOException {
int status = httpResponse.getStatusLine().getStatusCode();
switch (status) {
case HttpStatus.SC_OK:
String result = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
return result;
default:
return null;
}
}
});
} catch (ClientProtocolException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
httpClient.getConnectionManager().shutdown();
}
}
}
Androidの非同期通信の場合は、汎用的な目的に利用できるAsyncTaskLoaderに、通信という目的を持たせるためのコードを書く必要がありますね
結果
双方とも期待どおり、非同期で通信を行いコンテンツを取得できたようです。以下結果です
iOS7
シミュレータを起動し、ボタンを押すと、以下のようなログが表示されました
Android
Androidは自前のXPERIA Zグローバル版をつなぎ実行します。ボタンを押すと以下の様なログが表示されました
まとめ
今回は非同期通信処理の実装について比較してみました。
iOS7の方が目的に特化しているクラスであるため、単純な比較は難しいですが、やはりAndroid側のクラスは汎用的に使えるようにしているためか、記述するコード量は多い印象です。
今回は非同期通信について、素手で殴りあってもらいました。コスト、工数、コード量等の観点から見ると、結果としての勝利はiOS側でしょうか。柔軟性といった要素が入ってくるとまた別かもしれません
Androidも外部ライブラリを使うことで、かなりドーピングができるはずなので(VolleyやAquery等)、こちらもドーピング後の再戦をしてみると、また少し結果が違うかもしれませぬ
iOSでコードをAndroidと同じ目的を達するコードを書いてみると、え?これだけ?と思うようなコード量で目的が達成してしまうことがしばしばあるため、いちいちカルチャーショックを受ける今日このごろです。ほぼほぼコーディングなしでここまで出来るとは。iOS, Xcode恐るべし