API23でapache関連のモジュールが軒並み使えなくなっていることに加え、Volleyが未だにapacheモジュールを利用していることを理由(他にもmavenリポジトリがないとか)に、通信ライブラリをOkHttpへ移行することをよく勧めています。
しかし単に勧めるだけというのも投げっぱなし感があるので、移行に伴う各種処理の記述方法についても、共有していこうと思いました。
というわけでタイトルにも書いてますが、OkHttpを利用した(http上の)画像取得方法の超簡易版です。
該当コード
/**
* ResponseBodyの取得
*/
private static ResponseBody getResponse(@NonNull String url) {
Timber.d("get url:%s", url);
Request request = new Request.Builder().url(url).get().build();
try {
Response response = new OkHttpClient().newCall(request).execute();
if (!response.isSuccessful()) {
Timber.d("response error %d: %s", response.code(), response.message());
return null;
}
return response.body();
} catch (IOException e) {
Timber.e("IOException %s", e.getMessage());
return null;
}
}
/**
* 指定画像の取得(同期処理)
*/
@WorkerThread
private static Bitmap downloadFile(@NonNull String url) {
ResponseBody response = getResponse(url);
if (response == null) {
return null;
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(response.byteStream(), null, options);
Timber.d("original image w:%d h:%d", options.outWidth, options.outHeight);
options.inSampleSize = 1;
while ((options.outWidth * options.outHeight) / options.inSampleSize > MAX_IMAGE_SIZE * 4) {
options.inSampleSize *= 2;
}
Timber.d("options.inSampleSize: %d", options.inSampleSize);
options.inJustDecodeBounds = false;
response = getResponse(url);
if (response == null) {
return null;
}
Bitmap bitmap = BitmapFactory.decodeStream(response.byteStream(), null, options);
response.close();
return bitmap;
}
通信に成功すると、ResponseBodyにHTTPステータスコードやストリーム情報が格納されます。
byteStream()
によってInputStreamが取得できるため、通信のやりとり以外は通常のストリームからBitmap生成するやり方になります。
通信周りもresponse.isSuccessful()
でステータスコードのチェックが入っていますし、close()
処理もおおもとでException周りをキャッチしているので、ネストも少なく非常に見やすいんじゃないかなと思っています。
ただし、これだけの記述では キャッシュ処理がいっさい働いていないので、注意してください。
ちなみにnew OkHttpClient().newCall(request).execute()
の部分を
new OkHttpClient().newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
}
@Override
public void onResponse(Response response) throws IOException {
}
});
と変えることで、通信部分を非同期にできる(はず)ですが、今回の場合は結局Bitmap変換部分もあるので、まとめてAsyncTaskやThreadで処理したほうが見た目にもわかりやすいし、そもそもこのレベルの内容(取得して表示するだけ)であれば、PicassoやGlideを使った方がいいです(本末転倒)。