それは何のためですか?
![](https://habrastorage.org/files/04c/7e5/237/04c7e52372884d4b9a9bfb3b9968ef2d.jpg)
Android開発者には、HttpURLConnectionやApache Clientなどの組み込みAPIの代わりに、サードパーティライブラリを選択する多くの理由があります。 例:
- ネットワークコールをキャンセルする機能
- 並列クエリ実行
- 接続プールと既存のソケット接続の再利用
- サーバー応答のローカルキャッシュ
- メインスレッドまたはUIスレッドのブロックを回避するためのシンプルな非同期操作インターフェイス
- REST APIの便利なラッパー
- 再試行および遅延ポリシー
- 効率的な画像の読み込みと変換
- JSONシリアル化
- SPDY、http / 2をサポート
ちょっとした歴史
当初、Androidには2つのHTTPクライアントしかありませんでした:HttpURLConnectionとApache HTTPクライアント。 Googleの公式ブログ投稿によると、HttpURLConnectionには以前のバージョンのAndroidにいくつかのバグがありました。
Froyoより前のHttpURLConnectionには、あまり良くないバグがいくつかありました。 特に、読み取り可能なInputStreamでclose()を呼び出すと、接続プールが台無しになる可能性があります。
同時に、GoogleはApache HTTPクライアントを開発して移行したくありませんでした。
... APIのサイズが大きいため、後方互換性を失わずにこのライブラリを改善できません。 Androidチームは、Apache HTTPクライアントで積極的に作業していません。
Froyoより前は、ほとんどの開発者はOSバージョンに基づいて異なるクライアントを使用することを好みました。
Apache HTTPクライアントには、EclairとFroyoのバグがほとんどないため、これらのバージョンに最適です。 そして、ジンジャーブレッド以下では、HttpURLConnectionの方が優れています。 APIのシンプルさと軽量さは、Androidに適しています。 応答の透過的な圧縮とキャッシングは、速度を向上させ、バッテリー寿命を節約します。 新しいアプリケーションではHttpURLConnectionを使用する必要があります。
今日でも、GoogleのVolleyソースコードを調べると(少し後で説明します)、そのような遺産を見つけることができます。
if (stack == null) { if (Build.VERSION.SDK_INT >= 9) { stack = new HurlStack(); } else { // Prior to Gingerbread, HttpUrlConnection was unreliable. // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent)); } }
これは、開発者を苦しめるAndroidの断片化の典型的な例です。 2013年、SquareはOkHttpをリリースしたときにこの問題に注目しました。 OkHttpは、追加の依存関係を使用せずに、最上位のJavaソケットを直接操作するために作成されました。 JARファイルの形式で提供されるため、開発者はJVM(もちろんAndroidを含む)を備えた任意のデバイスで使用できます。 ライブラリへの移行を簡素化するために、SquareはHttpUrlConnectionおよびApacheクライアントインターフェイスを使用してOkHttpを実装しました。
![](https://habrastorage.org/files/dc7/e0a/d48/dc7e0ad48e304eab8ab2f8fd029f7110.png)
OkHttpは広範なコミュニティのサポートを得て、最終的に、GoogleはAndroid 4.4(KitKat)でバージョン1.5を使用することにしました。 2015年7月、Googleは、ApacheベースのAndroidHttpClientがAndroid 5.1(Lolipop)のリリースで廃止されたことを公式に認めました。
今日、OkHttpには次の大きな機能セットが付属しています。
- HTTP / 2およびSPDYのサポートにより、同じホストに送信されるすべての要求がソケットを共有できます
- クエリの集約により待ち時間が短縮されます(SPDYが利用できない場合)
- ダウンロードした情報の重みを軽減するための透過的なgzip
- 応答キャッシングを使用すると、リクエストが繰り返されている間にネットワークを操作する必要がなくなります。
- 同期ブロッキング呼び出しとコールバックを使用した非同期呼び出しの両方をサポート
OkHttpの私のお気に入りの部分は、非同期リクエストをいかに美しく正確に操作できるかです。
private final OkHttpClient client = new OkHttpClient(); public void run() throws Exception { Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt") .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Request request, Throwable throwable) { throwable.printStackTrace(); } @Override public void onResponse(Response response) throws IOException { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); System.out.println(response.body().string()); } }); }
これは非常に便利です。ネットワークでの作業がUIストリームに含まれていないためです。 実際、Android 3.0(Honeycomb、API 11)以降、別のスレッドでネットワークを操作することが必須になっています。 HtttpUrlConnectionで同様の何かを実装するには、AsyncTaskまたは別のスレッドを使用して、大きな(または恐ろしい)コンストラクトを構築する必要があります。 キャンセルされたダウンロード、マージされた接続などを追加する場合、これはさらに複雑になります。
ちなみに、GoogleのVolleyと呼ばれるHTTPライブラリは、次のボーナスを提供してくれましたが、道端にとどまりませんでした。
- ネットワーク要求の自動スケジューリング
- 多くの同時ネットワーク接続
- 標準的なキャッシュの一貫性に従って、メモリおよびディスクでの透過的なキャッシュ。
- クエリの優先順位付けのサポート。
- APIリクエストをキャンセルします。 単一のリクエストとブロック全体の両方をキャンセルできます。
- たとえば、繰り返しや延期のための簡単なセットアップ。
- ネットワークからユーザーインターフェイスを非同期で正しく簡単に設定できるようにする厳密なシーケンス。
- デバッグおよびトレースツール
![](https://habrastorage.org/files/6ce/fae/2d4/6cefae2d41fc45eea0067610c35e8906.png)
VolleyがHttpUrlConnectionの最上位にあるものは何でも。 JSONまたはイメージを取得する場合、VolleyにはImageRequestやJsonObjectRequestなどの特別な抽象化があり、HTTPペイロードを自動的に変換するのに役立ちます。 また、注目すべきは、Volleyがハードコーディングされたネットワークプールサイズを使用していることです。
private static final int DEFAULT_NETWORK_THREAD_POOL_SIZE = 4;
OkHttpがThread.PoolExecutorの最大値がInteger.MAX_VALUEであるすべての呼び出しにスレッドを使用する場合:
private int maxRequests = 64; private int maxRequestsPerHost = 5; executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
その結果、ほとんどの場合、OkHttpはより多くのスレッドを使用することでより高速に動作します。 何らかの理由でVolHttpとともにOkHttpを使用する場合、HttpURLConnectionの代わりにOkHttpからの要求/応答APIを使用するHttpStackの実装があります。
HTTPクライアントは、特に無限のスクロールと画像変換をサポートするアプリケーションをサポートするために進化を続けました。 同時に、REST APIは業界標準になり、すべての開発者はJSONとのシリアル化やREST呼び出しのJavaインターフェイスへの変換などの一般的なタスクを処理しました。 これらの問題を解決するライブラリが登場するまで、それほど時間はかかりませんでした。
- レトロフィット-RESTインターフェースと対話するためのタイプセーフなHTTP Androidクライアント
- Picasso-Android用の画像をダウンロードおよびキャッシュするための強力なライブラリ
Retrofitは、JavaコードとRESTインターフェース間の橋渡しをします。 プロジェクトにHTTP APIをすばやく含めることができ、自己文書化実装を生成します。
public interface GitHubService { @GET("/users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user); } Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com") .build(); GitHubService service = retrofit.create(GitHubService.class);
すべてに加えて、RetrofitはJSON、XML、プロトコルバッファーへの変換をサポートしています。
一方、ピカソは、画像指向のHTTPライブラリを提供します。 たとえば、1行でビューに画像をアップロードできます。
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
PicassoとRetrofiは、OkHttpClientを標準のHTTPクライアントとして使用するように構成されています。 ただし、必要に応じて、HttpURLConnectionクライアントを指定できます。
グライドはピカソに似ています。 GIFアニメーション、サムネイルのサムネイル生成、静止画像などの高度な機能を提供します。 完全な比較はここにあります 。
Facebookは最近、モバイルアプリケーションで使用するFrescoライブラリのソースコードを公開しました。 際立った重要な機能の1つは、長いGC(ガベージコレクター)を回避するためのビットマップのカスタムメモリ割り当て戦略です。 Frescoは、ashmemと呼ばれる領域にメモリを割り当てます。 このメモリ領域にアクセスするには、C ++で記述された部分とJavaの部分の両方からアクセスするために、いくつかのトリックが使用されます。 ネットワークからのCPUとデータの消費を減らすために、このライブラリは3つのキャッシュレベルを使用します。RAMに2つ、内部ストレージに3つです。
![](https://habrastorage.org/files/f4a/566/82b/f4a56682b43d48f99bb934a3bb52f405.png)
同じ図でライブラリ間の関係を示すことが必要であることがわかりました。 ご覧のとおり、HTTPは常に高レベルライブラリの下部にあります。 単純なHttpUrlConnectionまたは最新のOkHttpClientから選択できます。 PacketZoom Android SDKの開発時にこの互換性を使用します。これについては、次の投稿で説明します。
![](https://habrastorage.org/files/eea/a92/b38/eeaa92b3868d460b89381e96af6483b1.png)
最近、 HTTPライブラリのパフォーマンスを互いに比較しましたが、このトピックは別の考慮に値します。 このレビューにより、各ライブラリの長所と短所に関する基本的なアイデアが得られ、適切な選択ができるようになりました。 私たちからのより興味深いAndroidネットワーキングの投稿をお楽しみに。