SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

BizReach Tech Blog

Android 8.0とAndroid Studio 3.0で始めるReactive Extensionsを用いたアプリ開発

BizReach Tech Blog 第2回


開発を便利にするライブラリ

 Java/Androidには、便利で実績の多いライブラリがたくさんあります。本アプリでは、開発を便利にするライブラリとして下記を導入します。

  • lombok
  • Timber
  • Lightweight-Stream-API
  • RxJava2
  • RxAndroid

 執筆時点での最新バージョンを指定したbuild.gradleは以下のようになります。

dependencies {
    ...略...

    compileOnly 'org.projectlombok:lombok:1.16.18'
    annotationProcessor 'org.projectlombok:lombok:1.16.18'

    compile 'com.jakewharton.timber:timber:4.5.1'

    compile 'com.annimon:stream:1.1.9'

    compile 'io.reactivex.rxjava2:rxjava:2.1.3'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
      
    ...略...
}

 簡単に各ライブラリの利便性について記載します。

Lombok

 @AllArgsConstructor、@NoArgsConstructor、@Data、@Setter、@Getterなどのアノテーションを付与することでコンストラクタやgetter/setterを記述する手間を省いてくれます。

Timber

 フォーマットを扱えるログ出力APIを提供します。また、デバッグビルドのみログを出力したい、リリースビルド時はバグトラッカーに出力したいといった制御を簡単に行うことができるライブラリです。

Lightweight-Stream-API

 Optional、Stream API互換API、java.util.functionパッケージ互換インターフェースを提供します。他にも、Java 8標準では存在しないThrowableConsumerインターフェースなどの例外に対応したFunctionalInterfaceであるThrowableXXXシリーズも有用です。

RxJava2

 Javaでリアクティブプログラミングを行うためのライブラリです。RxJavaの2.xバージョンではReactive Streamsを実装しています。詳しくはRxJava 2.xで導入されたReactive Streamsもご参照ください。

RxAndroid

 RxJava2をAndroidで利用するためにandroid.os.Looperからio.reactivex.Schedulerを生成するAPIと、AndroidのMAINスレッドで動作するSchedulerの取得APIを提供します。

ユーザーリストフラグメントの作成

 まずは、チャット相手をリスト表示する画面をFragmentで実装します。この画面の完成図は以下のとおりです。

レイアウト

 このFragmentのレイアウトは、下図のようにしています。

 「画面上部から引っ張って更新」のUIを実現するためにSwipeRefreshLayoutを配置し、その内部には、ユーザーリストを表示するためのRecyclerViewを配置しています。 最後に配置したAppCompatTextViewは、ユーザーリストが空の場合にメッセージを表示するためのViewです。

 リストデータを表示する部分は、ListViewでも同じUIを実現できますが、RecyclerViewにはViewHolderパターンを前提とした扱いやすいAdapterクラス、アニメーションカスタマイズのしやすさ、Material Designを実現するDesign Supportライブラリとの親和性などの利点があり、もはやListViewを選択する理由は限りなく小さくなっていると言えます。

 AppCompatTextViewに限らず、サポートライブラリが提供している標準Viewの代替クラスは、OSバージョンの違いを吸収して新機能を利用できる利点があるので、積極的に採用して良いと思います。

 これらのView部品を利用するために、以下のライブラリを追加しておきます。

  • support-v4
  • appcompat-v7
  • recyclerview-v7

 build.gradleは、こちらです。

dependencies {
    ...略...
    
    // Android Studioで生成したプロジェクトなら最初から設定されています
    implementation 'com.android.support:support-v4:26.1.0'
    
    compile 'com.android.support:appcompat-v7:26.1.0'
    
    compile 'com.android.support:recyclerview-v7:26.1.0'
    
    ...略...
}

Viewのバインディング

 ユーザーの入力情報を受け取ったり、ユーザーへ情報を表示するためには、Viewからデータを受け取ったり渡したりする必要がありますが、これを実現する方法としては大きく2つの方法が考えられます。

  • Viewバインディング:Viewの参照をActivityやFragmentに持たせ、ActivityやFragmentではViewを直接更新する
  • Dataバインディング:昨今のjavascript界隈で見られるような、Viewにデータをバインディングし、ActivityやFragmentではデータを更新するといった役割分担を行う

 今回は、Viewバインディングを採用します。まずは、参照したいViewへidを設定しておきます。

<FrameLayout ...>
    
    <android.support.v4.widget.SwipeRefreshLayout
        ...
        android:id="@+id/refresh_layout">
        
        <android.support.v7.widget.RecyclerView
            ...
            android:id="@+id/recycler_view" />
    
    </android.support.v4.widget.SwipeRefreshLayout>
    
    <android.support.v7.widget.AppCompatTextView
        android:id="@+id/empty_text"
        ... />
    
</FrameLayout>

ViewバインディングかDataバインディングか

 Androidが提供するData Bindingライブラリを利用すれば、Viewにデータをバインディングする方法を採ることができます。しかし、筆者の個人的な意見ですが、まだData Bindingライブラリがもたらすメリット(ビュー操作の分離によるコード簡略化など)は、そのデメリット(自由度が高く、特にチーム開発ではスパゲティコードを産み出しやすい)を上回っておらず、導入は時期尚早ではないかと思います。

 次は、フラグメントクラスにView変数を用意し、onCreateView()メソッドでViewの参照を取得します。この手順は、以前のAndroid開発ではButterKnifeライブラリを使うのが定番の一つでした。しかし、Android 8.0時代(=compileSdkVersionが26以上)に突入した今であれば、Androidの標準的な方法を採用するのが良いと思います。

public class UserListFragment extends Fragment {
    
    private SwipeRefreshLayout mRefreshLayout;
    
    private RecyclerView mRecyclerView;
    
    private AppCompatTextView mEmptyText;
    
    ...
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final View root = inflater.inflate(R.layout.fragment_user_list, container, false);
        
        // Viewの参照を取得
        mRefreshLayout = root.findViewById(R.id.refresh_layout);
        mRecyclerView = root.findViewById(R.id.recycler_view);
        mEmptyText = root.findViewById(R.id.empty_text);
        
        return root;
    }
    
    ...
    
}

 Android 8.0では、View#findViewById()メソッドがジェネリクスに対応しました。そのため、下記の例に示すような明示的キャストは、もはや不要です。

mRefreshLayout = (SwipeRefreshLayout) root.findViewById(R.id.refresh_layout);

ButterKnifeを使う場合

 compileSdkVersionが更新できない状況や、View変数とバインド対象を識別するidを近い場所に記述したい場合はButterKnifeを使いましょう。

 フラグメントのクラスにView変数を用意して、Viewのidを指定した@BindViewアノテーションを付与します。

public class UserListFragment extends Fragment {
    
    @BindView(R.id.refresh_layout)
    SwipeRefreshLayout mRefreshLayout;
    
    @BindView(R.id.recycler_view)
    RecyclerView mRecyclerView;
    
    @BindView(R.id.empty_text)
    AppCompatTextView mEmptyText;
    
    ...
}

 また、onCreateView()メソッドでViewバインディング、onDestroyView()メソッドでその解除を行います。

public class UserListFragment extends Fragment {
    private Unbinder mUnbinder;
    
    ...
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final View root = inflater.inflate(R.layout.fragment_user_list, container, false);
        
        // Viewバインディング
        mUnbinder = ButterKnife.bind(this, root);
        
        return root;
    }
    
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        
        // Viewバインディング解除
        mUnbinder.unbind();
    }
    
    ...
}

 build.gradleを下記のように設定してください。また、ButterKnifeはバージョン8.0.0以降で、ライブラリ自体にProGuardの設定が含まれるようになったため、ButterKnifeのProGuard設定は不要です。

dependencies {
    ...略...
    
    compile 'com.jakewharton:butterknife:8.8.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
    
    ...略...
}

次のページ
通信処理を実装する

この記事は参考になりましたか?

BizReach Tech Blog連載記事一覧

もっと読む

この記事の著者

岩井 友希(株式会社ビズリーチ)(イワイ トモキ)

SIer、フリーランスを経て、2015年にビズリーチへ入社。 Java、Python、Android、iOS、Linuxたまにセキュリティとかのキーワードに反応するエンジニアです。 github:https://github.com/TomokiIwai 株式会社ビズリーチについて:https://www.bizreach.co.jp/recruit/

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/10676 2018/10/17 15:47

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー