いまどきの MVP 実装パターンを眺めるべし「Android Architecture Blueprints」

このような, 質問がありました.

こんにちは。

私はアプリの開発を2年ほどやっているものです。
しかし, いつも似たようなコードの繰り返しばかりで少しも進歩していないように思っています。

小さい会社なので, モバイルアプリ開発者は私だけで, だれも私のコードを見ることがないので, 私のコードの間違いを指摘されることはなく, 会社で開発されている他のコードを見ることもありません。

最新技術を利用しすばらしい実装を行っているオープンソースアプリのコードを勉強したいです。

そのようなアプリをどこで見つけたらよいか教えて下さい。

よろしくお願いいたします。

I would like to study some up-to-date open source apps, preferably with material design, do you have any suggestions? : androiddev

このような環境で日々を過ごし, 似たようなことを考えてる開発者は多いと思います。

以下のサイトはいかがでしょうか. よくある ToDo アプリでのサンプルとなっています.

Android Architecture Blueprints [beta] - A collection of samples to discuss and showcase different architectural tools and patterns for Android apps.

ここでフォーカスされているのは, 構造, 設計, テスト, メンテナンスのしやすさですが, リファレンスとして, または, アプリ開発のスタート地点として利用できます.

MVP (基本的な Model-View-Presenter)

googlesamples/android-architecture at todo-mvp

このサンプルはすべての基本となります. 構造を持つフレームワークを使わないシンプルな Model-View-Presenter パターンの実装例です. ローカル/リモートのデータソースである Repository を手作業で Dependency Injection しています. 非同期処理はコールバックを利用しています.

mvp

MVP + Loader

googlesamples/android-architecture at todo-mvp-loaders

Repository から Loader を使ってデータを取得します.

- コールバックなしで Repository 内のデータを非同期で読み込むことができる.
- データソースを監視しており, Repository の内容が変化すると新しい結果として配送できる.
- 画面回転のあと自動的に直近の Loader を再接続できる.

mvp-loaders

MVP + Loader + ContentProvider

googlesamples/android-architecture at todo-mvp-contentproviders

Repository からのデータ取得に ContentProvider を使います.

- 構造化されたデータへのアクセス操作可能.
- 別プロセスで稼働しているコードからデータへ接続できる標準的なインターフェースとなる.

mvp-contentproviders

MVP + DataBinding

googlesamples/android-architecture at todo-databinding

DataBiding ライブラリを利用して, UI要素にデータとアクションをバインドしています. 厳格には Model-View-ViewModel や Model-View-Presenter パターンではありません. ViewModel と Presenter 両方使用しています.

DataBinding ライブラリは, データとUI要素を連携する重複するコードを削減してくれます.

- レイアウトファイルがUI要素へのバインドに利用されている.
- 同時にイベントもアクションハンドラーと結合されている.
- データの監視が可能で必要であるときには自動で更新するようにセットすることができる.

mvp-databinding

MVP + Clean Architecture

googlesamples/android-architecture at todo-mvp-clean

Clean Architecture に基づいており, Presentation と Repository レイヤーの間に Domain レイヤーが存在して, アプリを3つのレイヤーに分けています.

Domain レイヤーでは, すべてのビジネスロジックを収納しており, Presenter に使われる use-case か interactor と命名されたクラスから始まる. これらの use-case は Presentation レイヤーから作ることができるすべての実装可能なアクションを提供します.

mvp-clean

その他

その他, 最近流行のフレームワークや考え方を考慮しての実装サンプルも続々と作成中のようです.

Architecture Blueprints の非同期処理実装にみる Android SDK の方向性

MVP + Dagger2
MVP + RxJava
MVP + Fragmentなし

非常に柔軟性のある使えるサンプルとなると思われます. ぜひご確認あれ.

Architecture Blueprints の非同期処理実装にみる Android SDK の方向性

Hacker News Radio (翻訳) - Google Play の Android アプリ


モンスターの居場所がわかる「POKÉVISION」

便利ですよね.

PokéVision — Find, locate and track Pokemon near you or anywhere in the world live & realtime in Pokemon GO!

PokéVision_—_Find__locate_and_track_Pokemon_near_you_or_anywhere_in_the_world_live___realtime_in_Pokemon_GO_

なんでも, 下調べは大事です.

「ポケモンGO」の生みの親、解析ツールPokeVisionを規約違反と明言 - iPhone Mania


CoordinatorLayout がわかりづらいのは デフォルト のせい?

よくある画面要素の組み合わせ ActionBar + RecyclerView + FAB.

ActionBar 部分をスクロール時に上にスライドさせて消したいですよね!

まずは CoordinatorLayout で囲みます.

レイアウトはこんなかんじの構成ですね.


<CoordinatorLayout>
  <AppBarLayout>
    <Toolbar />
  </AppBarLayout>
  <RecyclerView />
  <FloatingActionButton />  
</CoordinatorLayout>

ここでは, 連携する挙動の始まりとなる「きっかけ」を RecyclerView のスクロールとしましたが, 以下の View や Layout は, デフォルトで同様に「きっかけ」にすることができます.

HorizontalGridView
NestedScrollView
RecyclerView
SwipeRefreshLayout
VerticalGridView

NestedScrollingChild | Android Developers

よく画面をみてみると, RecyclerView の最上段をみることができないようになってますね!

20160414-190459_1

それは, CoordinatorLayout は FrameLayout だからです.

CoordinatorLayout is a super-powered FrameLayout.

CoordinatorLayout | Android Developers

でも, とりあえず無視します.

次に, アクションバー部分が「きっかけ」に反応して「ふるまう」するようにします.

AppBarLayout または Toolbar に, 属性「app:layout_behavior」をつけて, 「ふるまう」時の挙動を追加したくなります.

でも, 必要なかったりします.

ふるまいを記述する Behavior は, デフォルトですで に AppBarLayout にアノテーションを利用してセットされているからです.


@CoordinatorLayout.DefaultBehavior(AppBarLayout.Behavior.class)
public class AppBarLayout extends LinearLayout {

Cross Reference: AppBarLayout.java

なので, ふるまい方の種類だけをその子である Toolbar 記述します.


<CoordinatorLayout>
  <AppBarLayout>
    <Toolbar
      app:layout_scrollFlags="scroll|enterAlways" />
  </AppBarLayout>
  <RecyclerView />
  <FLoatingActionButton />  
</CoordinatorLayout>

ここで, 動かしてみます.

20160414-191401_1

アクションバーが消えていくようになりましたね!

最後に, RecyclerView 自体も「ふるまわ」せます.

AppBarLayout のふるまい方と同じふるまい方をするように同じ Behavior をセットします.


<CoordinatorLayout>
  <AppBarLayout>
    <Toolbar
      app:layout_scrollFlags="scroll|enterAlways" />
  </AppBarLayout>
  <RecyclerView
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />
  <FLoatingActionButton />  
</CoordinatorLayout>

ここでいきなり現れた文字列 @string/appbar_scrolling_view_behavior は, デフォルトでセットされている


android.support.design.widget.AppBarLayout$ScrollingViewBehavior

のことです.

AppBarLayout にデフォルトで設定されているものと同じですね.

ここで, また動かしてみます.

20160414-195431_1

AppBarLayout の Behavior と同じものを RecyvlerView にもセットしたので, 同じように動きます.

スクロール時にAppBarと同じように開閉スライドすることになるので, RecyclerView との重なり合いがなくなり RecyclerView の最上段も表示されるようになりましたね!

実際の簡略化していないレイアウトを貼っておきます.


<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
  <android.support.design.widget.AppBarLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:theme="@style/AppTheme.AppBarOverlay">
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:title="@string/app_name"
        app:layout_scrollFlags="scroll|enterAlways" />
  </android.support.design.widget.AppBarLayout>
  <android.support.v7.widget.RecyclerView
      android:id="@+id/recycler_view"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      app:layout_behavior="@string/appbar_scrolling_view_behavior" />
  <android.support.design.widget.FloatingActionButton
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginRight="16dp"
      android:layout_marginBottom="16dp"
      android:layout_gravity="right|bottom"
      android:src="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>

以上のように, レイアウトファイルだけを編集するだけで, インタラクティブな挙動を画面の要素たちに行わせることができるので, 便利な気もしますね!!

→ 少しややこしいので「まとめ」ようとしてつづく (作成中)