5系の新しいapiの実装方法を調べた(+RxJava)


今回調査したのは、

* 左上のクルクルする矢印アイコンの実装方法
* リップルエフェクト(波紋のように広がるエフェクト)の実装方法
* RecyclerViewの実装方法
* サポートライブラリがどこまで対応してるか

加えて、最近流行っているRxJavaも気になっていたので、[ネットワーク通信] -> [リストアダプターに流し組む]部分をRxJava(+Retrofit)で実装しました


#### クルクルする矢印アイコンの実装方法

クルクルする矢印のアイコンはサポートライブラリで提供されていて、
利用するにはappcompat-v7をいれます

```gradle
compile 'com.android.support:appcompat-v7:21.+'
```

あとはこんな感じのテンプレコードを書けば動きます

```java
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.start, R.string.stop);
drawerToggle.setDrawerIndicatorEnabled(true);
drawerLayout.setDrawerListener(drawerToggle);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
```

```java
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        return drawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        drawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        drawerToggle.onConfigurationChanged(newConfig);
    }
```

ActionBarDrawerToggleってv4のサポートライブラリの方にもあって、それに気づかないと結構ハマります

#### リップルエフェクト(波紋のように広がるエフェクト)の実装方法

リップルエフェクトもデフォルトのものは、SDKが提供してくれていて、
エフェクトを掛けたいviewのbackgroundを指定します

```xml
android:background="?android:attr/selectableItemBackground"
```

実はもう一種類あって

```xml
android:background="?android:attr/selectableItemBackgroundBorderless"
```
こっちはviewを跨いだ波紋が広がるエフェクトになるっぽい? のですが、minSDKが21なのでLollipopにしか使えません


#### RecyclerViewの実装方法
Adapterを作るのはListViewを同じ、RecyclerView.Adapterの実装は簡略化すると概ねこんな感じ、

```java
public class EntryAdapter extends RecyclerView.Adapter<EntryAdapter.ViewHolder> {
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    // viewをinflateしてViewHolderを作成する
        View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.cell_xxx, parent, false);
        return new ViewHolder(view);
    }
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
    // getView相当の処理(view.setText() etc...)
    }
    @Override
    public int getItemViewType(int position) {
        return // viewTypeを返す;
    }
}
```
昔のAdapterの実装とほとんど変わんないのですが、新しい概念としてViewTypeというのが追加されてて
複数のviewをレンダリングするタイプのリストを作成したい場合はgetItemViewTypeをOverrideしてよしなに出来ます
Activity側はこんな感じ

```java
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
entryAdapter = new EntryAdapter();
recyclerView.setAdapter(entryAdapter);
```

#### サポートライブラリがどこまで対応してるのか

これは正直ちゃんと調べてないのでわからないですが、少なくとも上の3つはサポートライブラリで対応できました
(気になるの他に何かあったかな..)

#### RxJava

[ネットワーク通信] -> [リストアダプターに流し組む]は下のコードような感じ
そこそこ複雑なリストの処理してるけど、完結でわかりやすく書ける
学習コスト低いのでコスパ的に考えるとかなりいい気がする
特にRetrofitがRxjava対応していてホント便利だった。
使い方は、[wiki](https://github.com/ReactiveX/RxJava/wiki/The-RxJava-Android-Module)と[サンプル](https://github.com/andrewhr/rxjava-android-example/blob/master/app/src/main/java/com/example/rx/ComposeMessageActivity.java)見れば簡単な処理ならすぐ出来そう

```java
        category.observable(app)
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe(() -> {
                // something..
                })
                .onErrorReturn(throwable -> {
                // something..
                })
                .map(entries -> {
                // something..
                })
                .flatMap(Observable::from)
                .groupBy(entry -> {
                // something..
                })
                .subscribe(observable -> {
                    if (observable.getKey() == EntryType.onlyTitle) {
                        observable.subscribe(entryAdapter::add);
                    } else if (observable.getKey() == EntryType.WithImage) {
                        observable
                                .buffer(2)
                                .filter(// something )
                                .subscribe(entryAdapter::add);
                    }
                });
```

#### 今回作ったアプリ
<img width=400 src="http://i.gyazo.com/d1fb0337aa5bd9fe1bd899bad3d00b25.png">
[<img src="http://f.st-hatena.com/images/fotolife/h/hatenablog/20141023/20141023191636.png?1414059438">](https://play.google.com/store/apps/details?id=com.kazy.twol)

良かったらサンプルアプリとしてご活用下さい