画像読み込みライブラリ Glide の v4 を試してみる

**この記事では Glide 4.0.0 RC0 を使っています**

## 短い概要

1. Glide 4 がそろそろリリースされるようです
2. Glide 4 には Annotation Processor を使ったコード生成機能が用意されています
3. `GlideModule` を使った実装がある場合、 `AndroidManifest.xml` に定義を書かなくても良くなりました
4. v3 から v4 は非互換の変更が入っていて、[マイグレーションが必要です](http://bumptech.github.io/glide/doc/migrating.html)

## はじめに

[Glide](https://github.com/bumptech/glide) は Android 開発において Web やローカルにある画像を読み込んで ImageView に表示するためのライブラリです。 Square の [Picasso](http://square.github.io/picasso/) や Facebook の [Fresco](http://frescolib.org/) と同じく、非常に人気のあるライブラリと言って良いでしょう。特徴としてはアニメーション GIF を表示できること、 Picasso と同じような Fluent API を持ち、 ImageView をターゲットに出来ることだと思います。

Glide はしばらく v3 系が続いてきましたが、 2017/05/17 に [4.0.0 RC0 が公開されました](https://github.com/bumptech/glide/releases)。また、 GitHub Releases のページには興味深いことが書かれています。

> Glide 4.0 is used internally by a variety of teams at Google and the library is considered stable internally. I expect that there will be more external users who may uncover issues that haven't come up internally. As a result I'm releasing this as an RC. If we don't uncover significant issues with stability or in the API, I expect a non-RC release shortly.

* Google 内部で使われていて、安定していると考えていること
* 内部だけでは見つかれない問題があるかもしれないから RC として公開したこと
* 問題無ければ RC を外すこと

ざっとこんな内容でしょうか。また、今後のリリーススケジュールに関しても書かれており、毎月 15 日前後にバージョンアップが行われる (変更がなければスキップされる) ことが書かれています。

どうやらすぐに Glide は v4 になりそうですので、少しだけ試してみました。

## 試してみる

### build.gradle

Glide v4 を試す前にすぐに分かるのは、 `build.gradle` の `dependencies` セクションに記述する項目が増えていることです。

```groovy
compile 'com.github.bumptech.glide:glide:4.0.0-RC0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.0.0-RC0'
```

アノテーションプロセッサを使ったコード生成による何かが行われるようです。

### インテグレーション

Web から画像を読み込むときの HTTP クライアントを OkHttp や Volley に変更するためのインテグレーションライブラリも v3 系と同様に使うことが出来ます。また、 [Glide v4 のドキュメント](http://bumptech.github.io/glide/)を見ると [RecyclerView インテグレーションライブラリも追加](http://bumptech.github.io/glide/int/recyclerview.html)されています。

```groovy
compile 'com.github.bumptech.glide:okhttp3-integration:4.0.0-RC0'
compile 'com.github.bumptech.glide:recyclerview-integration:4.0.0-RC0@aar'
```

しかし、**ドキュメントに書かれている方法では RecyclerView インテグレーションライブラリは追加できませんでした**。上述のように `@aar` の指定が必要のようです。

### Glide Module

例えば自分で定義した OkHttp 3 のインスタンスを Glide の HTTP クライアントにしたい場合、 Glide v3 では `GlideModule` を実装したクラスを用意する必要がありました。また、実装したクラスについての宣言を `AndroidManifest.xml` に記述する必要もありました [^1] 。

Glide v4 では `@GlideModule` アノテーションと `AppGlideModule` を継承した実装を行います。

```java
@GlideModule
public class MyOkHttp3GlideModule extends AppGlideModule {
    @Inject
    OkHttpClient okhttpClient;

    @Override
    public void registerComponents(Context context, Registry registry) {
        ((App) context.getApplicationContext()).getComponent().inject(this);

        registry.replace(
            GlideUrl.class,
            InputStream.class,
            new OkHttpUrlLoader.Factory(okhttpClient)
        );
    }
}
```

このコードは自分が定義した OkHttpClient を Glide 内で使うためのものです。 `AppGlideModule#registerComponents` メソッド内で OkHttpClient のインスタンスを手に入れるために Dagger 2 を使ってインスタンスを取得しています。

コンストラクタインジェクションを使って依存の解決を行いたいところですが、 `@GlideModule` アノテーションによってコンパイル時に自動生成される `GeneratedAppGlideModuleImpl` というクラス内ではデフォルトコンストラクタへのアクセスが行われているため、フィールドインジェクションで解決しています。

Glide v4 では実装したクラスの宣言を `AndroidManifest.xml` へ記述する必要はありません。

### Glide と GlideApp

Glide を使う場合、

```java
Glide.with(this)
    .load(/* Image URL */)
    .placeholder(/* Placeholder Drawable */)
    .error(/* Error Drawable */)
    .into(/* Target ImageView */);
```

このようなカタチのコードが基本となりますが、 Glide v4 では `.placeholder()` や `.error()` メソッドがありませんでした。 Glide v4 では読みこみ元の画像の指定と、読みこみ先の ImageView の指定しか出来ません。

そこで、オプション要素は `RequestOptions` という別クラスを使って定義する形に変更されています。このインスタンスを `Glide#apply` メソッドに渡すことでこれまでと同じ動きになります。

```java
RequestOptions requestOptions = new RequestOptions();
requestOptions.placeholder(/* Placeholder Drawable */);
requestOptions.error(/* Error Drawable */);

Glide.with(this)
    .load(/* Image URL */)
    .apply(requestOptions)
    .into(/* Target ImageView */);
```

一方、 Glide v4 では **`GlideApp`** という新しいクラスがあります。これはアノテーションプロセッサによって生成されるクラスで、これまでの `Glide` API が提供していたものは `GlideApp` が提供することになります。

```java
GlideApp.with(this)
    .load(/* Image URL */)
    .placeholder(/* Placeholder Drawable */)
    .error(/* Error Drawable */)
    .into(/* Target ImageView */);
```

`RequestOptions` や `@GlideModule` アノテーションが付与されたモジュールは `GlideApp` に統合されるため、 Glide v4 ではこのクラスをメインに使っていくことになると思います。

また、この `GlideApp` という名前は別名に変更することが出来ます。 `@GlideModule` アノテーションには `glideName` という String 型のプロパティがあるため、ここに使用したい名前を書くことが出来ます。

```java
@GlideModule(glideName = "MyGlideApp")
```

この例では `MyGlideApp` にしていますので、 Glide へのアクセスも

```java
MyGlideApp.with(this)
```

というものに変わります。

## 最後に

Glide もアノテーションプロセッサを使ったコード生成が行われるようになり、 Glide v3 からの移行は破壊的な変更を伴うことになりそうであることが分かりました。 Picasso と比較されることが多いライブラリですが、 v4 の変更によって使い勝手に変化が生じるため、単純な比較はできなくなりそうです。 Picasso も新バージョンが出なくなって久しいですが、 Glide がアノテーションプロセッサを使う形になったことで今後のバージョンアップがどのようなものになるか楽しみになりました。

## 注釈

[^1]: http://gfx.hatenablog.com/entry/2016/05/16/141001