[iOSとAndroid機能比較] 非同期通信

非同期通信

今回は非同期通信の処理を比較してみます。外部ライブラリ等を使わずに素手で殴りあってみます。

目標

「指定した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

シミュレータを起動し、ボタンを押すと、以下のようなログが表示されました

スクリーンショット 2013-09-18 2.58.06

Android

Androidは自前のXPERIA Zグローバル版をつなぎ実行します。ボタンを押すと以下の様なログが表示されました

スクリーンショット 2013-09-18 3.02.00

まとめ

今回は非同期通信処理の実装について比較してみました。
iOS7の方が目的に特化しているクラスであるため、単純な比較は難しいですが、やはりAndroid側のクラスは汎用的に使えるようにしているためか、記述するコード量は多い印象です。

今回は非同期通信について、素手で殴りあってもらいました。コスト、工数、コード量等の観点から見ると、結果としての勝利はiOS側でしょうか。柔軟性といった要素が入ってくるとまた別かもしれません
Androidも外部ライブラリを使うことで、かなりドーピングができるはずなので(VolleyやAquery等)、こちらもドーピング後の再戦をしてみると、また少し結果が違うかもしれませぬ

iOSでコードをAndroidと同じ目的を達するコードを書いてみると、え?これだけ?と思うようなコード量で目的が達成してしまうことがしばしばあるため、いちいちカルチャーショックを受ける今日このごろです。ほぼほぼコーディングなしでここまで出来るとは。iOS, Xcode恐るべし