Tellme for Androidで使ったライブラリやツールを紹介するよ | サイバーエージェント 公式エンジニアブログ

こんにちは。エンジニアの清水です。
昨年の7月まではフロントエンドエンジニアとして主にJavaScriptを書いていたのですが、2014年8月からネイティブエンジニアとしてAndroidアプリを作っていました。
4月からはまたフロントエンドの仕事もしています。

今回は、私が開発に携わったTellmeというQ&AサービスのAndroidアプリで利用したライブラリを紹介してみようと思います。サンプルコードも書く意欲が湧いたものは書いていきます。

テルミーってこんなアプリ

※ちなみにこんなアプリです

Libraries

ButterKnife

ButterKnifeはアノテーションを用いてView Injectionを行うライブラリです。
これを使うとonCreate/onCreateViewの中でfindViewByIdを書き連ねる必要がなくなります。
Activityで使ってみると下記のような感じでいけます。

class SampleActivity extends Activity {
    @InjectView(R.id.user_name) 
    TextView mUserName;


    @InjectView(R.id.user_avatar) 
    ImageView mUserAvatar;


    @OnClick(R.id.btn_follow)
    public void follow() {
        // call api
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sample);


        ButterKnife.inject(this);
    }
}

現状の最新版はv6.1.0ですが、次回メジャーバージョンアップ(v7.0.0)から@InjectView@FindViewに変わるらしいので、現在利用している方は注意しましょう。

Otto

Ottoは、いわゆるPub/SubをJavaで実現するためのライブラリです。
フロントエンド開発では、Backbone.EventsのようなEventBusやDOM Eventをカスタマイズしたものを使っていたので、同じような機能を使いたいと思い行き着いたのがOttoでした。
TellmeではAPIの戻り値を受け取ったり、Fragment - Fragment間、Fragment - Activity間のデータのやりとり等に使っています。

// api
mApi.loadNewArrival(new Callback<List<QuestionResponse>>() {
    @Override
    public void success(List<QuestionResponse> questionList) {
        // BusProviderは、Busインスタンスを保持するシングルトン
        // NewArrivalLoadedはResponse/Errorを格納し受信先へ渡すためのオブジェクト
        BusProvider.get().post(new NewArrivalLoaded(questionList));
    }


    public void failure(Error error) {
        BusProvider.get().post(new NewArrivalLoaded(error));
    }
});


// Fragment
public void onResume() {
    // イベントを受信できるように登録
    BusProvider.get().register(this);
}


public void onPause() {
    // イベントの受信を解除
    BusProvider.get().unregister(this);
}


@Subscribe
public void onNewArrivalLoaded(NewArrivalLoaded event) {
    if (event.isError()) {
        return;
    }


    // some code
}

同じ機能を提供するライブラリとして、greenrobotの提供するEventBusがあります。こちらのほうがOttoよりも高機能でパフォーマンスがいいらしいのですが、結局アノテーションでイベント受信先を定義できるOttoの方を選びました。
ただ、EventBusもv3.0でアノテーションをサポートするようなので、近いうちに”書きやすさ”という意味での差はなくなるかもしれません。

Retrofit

Retrofitを使うと、通信周りの処理が非常に簡素に記述できます。
基本的にinterfaceの定義をするだけですみます。

// API定義
public interface QuestionApi {
    @GET("/api/questions/newarrival.json")
    void loadNewArrival(
            @Query("since_id") Integer sinceId,
            @Query("max_id") Integer maxId,
            @Query("per") Integer per,
            Callback<List<QuestionResponse>> cb);
}


// 使い方
RestAdapter restAdapter = new RestAdapter.Builder()
    .setEndpoint("http://tell-me.jp")
    .setConverter(new GsonConverter(new Gson()))
    .build();


QuestionApi api = restAdapter.create(QuestionApi.class);
api.loadNewArrival(null, null, 20, new Callback<List<QuestionResponse>>() {
    @Override
    public void success(List<QuestionResponse> questionList) {
        // QuestionResponseはPOJO


    }


    @Override
    public void failure(RetrofitError error) {


    }
});

サンプルはコールバックを利用していますが、RxAndroidを併用すると結果をObservableで受け取ることもできます。
マルチパートリクエストにも対応しているので、画像アップロードだってお手のものです。

OkHttp

Retrofitと同じくsquare製のHttpクライアントです。SPDYにも対応していますが、Retrofitのついでに入れただけなので特に有効活用してないです^^;

Glide

画像の読み込みライブラリです。bumptechというのは、あれです。Googleに買収されたBumpです。
Glideは画像読み込み時にActivityやFragmentを指定することができます。これにより、対象のActivity/Fragmentのライフサイクルに沿った読み込み・開放処理をGlide側がいい感じに行ってくれるようです。
インターフェースはPicassoとほとんど変わらないので、Picasso使いなAndroidエンジニアなら特に違和感なく使えると思います。
アニメーションGIFが素のママで使えたり、細かくキャッシュ設定できる点がPicassoよりよいです。

Timber

ログをいい感じに出力してくれるライブラリです。
Android標準のログでデバッグ時に表示してリリース時には表示しない、みたいなことを実現しようと思うと、以下のようなコードになると思います。

if (BuildConfig.DEBUG) {
    Log.d(TAG, "foo");
}

これだと、毎回if文書いたりしてダルいですし、if文忘れてデバッグログが本番アプリで出力される、とかあるあるです。
そこでこのTImber。Treeインターフェースを利用して、ログ出力の可否を自由に設定できます。
Applicationクラスで一度設定したら、後は特に条件分岐を加える必要もなくライブラリがよきに取り計らってくれます。
本番アプリでは基本ログ出力せず、エラーログをCrashlyticsに送りたい、というようなニーズにも簡単に対応できます。

IcePick

savedInstanceState関連の処理をアノテーションを利用して簡素にできるライブラリです。
Parcelable自動生成する系のライブラリと組み合わせる時は、同じ作者のAutoParcelがいいようです(AutoValueのAndroid移植版なので、またちょっと別の知識も必要になってきますが…)

Android-ObservableScrollView

ListView/ScrollView/WebViewに統一されたスクロールイベントのインターフェースを提供してくれるライブラリです。これを利用すると、Toolbarをスクロールで隠す/Floating Action Buttonをスクロールで隠すといったような処理を、一つにまとめることができます。もう、ListView/ScrollView/WebViewの三通りの実装をしなくてもよいのです。
サンプルも充実しており、非常に参考になります。

Retrolambda

Java8のラムダ式をAndroidでも使えるようにしてくれます。それ以上でもそれ以下でもありませんが、ラムダが使えるようになるだけでだいぶコードの見通しがよくなります。

// before
new Handler().post(new Runnable() {
    @Override
    public void run() {
        Timber.d("some code");
    }
});


// after
new Handler().post(() -> Timber.d("some code"));

Tools

Android Studioプラグイン

Android Parcelable code generator

Parcelableを使うのに必要なあの膨大なコードを自動生成してくれます。
List用のコードがうまく生成できなかったり不具合はいくつかありますが、ないよりはだいぶマシです。

Otto IntelliJ Plugin

上で紹介したOttoのイベント発信元と受信先を簡単に行き来できるようにするAndroid Studio/IntelliJ用のプラグインです。
Ottoを利用するとコールバックが減ってコードがスッキリする反面、どのイベントをどこでハンドリングしているかが分かりづらくなりがちなので、とても重宝しています。

Grunt

node.js製のタスクランナーです。
デザイナーさんに用意してもらった画像のdpi別バリエーションを作成・減色するために使用しています。

いきなりJavaScriptが出てきておや?と思うかもしれませんが、使えるものは言語を問わず使うと良いです。

grunt-resource-resizer

まだ発展途上ですが拙作の画像リサイズプラグインです。
一つ画像用意しておけば任意のサイズに一括で書き出してくれます。よさ気なものが見つからなかったので作りましたが、いいのがあったら教えてください。

grunt-image

弊社1000chさん謹製の画像最適化プラグインです。
メタ情報の削除だけでなく、減色もしてくれる優れものです。
詳しくはこのあたりをどうぞ

まとめ

いかがでしょうか。少しでも参考になったら幸いです。
こうして見てみると、Square/Jake神製のライブラリが結構多いですね。もうサンフランシスコに足を向けて眠れません。
同じ作者のライブラリを使いすぎるとなにかあった時に怖い気もしますが、まあOSSですしどうにかなるでしょう。

p.s. そろそろアメブロもMarkdownとシンタックスハイライト対応してほしいです

 

Written with StackEdit.