いまどきの 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


Related Categories :  GamesRecommendedTools


gradle 2.2.0-alpha3 で 「APK is not zip aligned」

なぜか apk アップロードで怒られる.

screen1

com.android.tools.build:gradle のバージョンが関係しているようです.

this issue should be fixed in alpha4.

Issue 212591 - android - gradle:2.2.0-alpha3 not zipalign apks - Android Open Source Project - Issue Tracker - Google Project Hosting

alpha4

これでOKです.


ネットワークライブラリ Volley を使うのをやめる時期なのでしょうか?

2013年 Google I/O で発表されたネットワークライブラリ Volley.

Sending a Simple Request | Android Developers

volley_arch

Which Android HTTP library to use? - PacketZoom Blog

もう三年も経つんですね.

このような質問.

私は, ネットワーク処理で Volley を使っています. しかし, Google は活発にメンテナンスしていないように思えます. 最初, Google は Play Store アプリに利用するためにそれを開発したということですが, 利用しているサードパーティのライブラリ一覧に明記されていないし, ほとんどの人が Retrofit (ベンチマークをみるとこちらのほうがよさそう) を使っています. Volley を使うのをやめる時期なのでしょうか?

で, 以下回答より.

「Google は活発にメンテナンスしていないように思えます」

これは, あなたが「活発なメンテナンス」をどう定義しているかによります. gitリポジトリで確認できるように, 開発は続いており, 過去1年でも数多くのコミットがされています.

platform/frameworks/volley - Git at Google

また, 今年の最初に Google は, 公式に Volley アーティファクト を, バージョン 1.0.0 として公開しています.

「利用しているサードパーティのライブラリ一覧に明記されていない」

Google は Play Store アプリを作成し, Volley も作成した. それゆえに, Google からみると, Volley はサードパーティのライブラリではありません. Google ではない人からみると Volley はサードパーティライブラリとなります.

「ほとんどの人が Retrofit を使っている」

Retrofit と Volley は同じではありません. Square の HTTP関連ライブラリ (OkHttp3, Retrofit, Picasso) 3つセットで同等なものとなり, それは Volley の能力を越えます.

Stack Overflow 上での話に関しては, 私は「ほとんどの人が Retrofit を使っている」とは思っていません.

「Volley を使うのを止める時期でしょうか?」

これには, あなたしか答えることができません. 重要な判断基準を持つのはあなただけで, ライブラリがその基準を満たすかどうか評価するのはあなただけです.

Is Android Volley Dead? - Stack Overflow

最近では, Google発のライブラリだけでなく, アプリや, SDKまでもが「Androidでは, こんなことが, これくらいできますよ」という高機能で複雑なサンプル的なショーケースのような意味合いが強くなってきてるように思えるけど, これを「実用的」というのか, どうなのかー.


2分で作れる「About Page」にみる Intent の作り方

Pocket の開発者の方なのかな.

以下のような記述のみで「About Page」が作成できるようです.


public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        View aboutPage = new AboutPage(this)
                .isRTL(false)
                .setImage(R.drawable.dummy_image)
                .addGroup("Connect with us")
                .addEmail("[email protected]")
                .addFacebook("the.medy")
                .addTwitter("medyo80")
                .addYoutube("UCdPQtdWIsg7_pi4mrRu46vA")
                .addPlayStore("com.ideashower.readitlater.pro")
                .addInstagram("medyo80")
                .addGitHub("medyo")
                .create();

        setContentView(aboutPage);
    }

medyo/android-about-page: Create an awesome About Page for your Android App in 2 minutes

こんなかんじになります.

20160425-115827_1

下の方の各アイテムをタップすると, 作成されたそれぞれの Intent で startActivity されるわけですが.


mContext.startActivity(element.getIntent());

どんな Intent なのか見てみましょう.

メール


Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("message/rfc822");
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{email});

Facebook


Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_BROWSABLE);

if (AboutPageUtils.isAppInstalled(mContext, "com.facebook.katana")){
  intent.setPackage("com.facebook.katana");
  int versionCode = 0;
  try {
    versionCode = mContext.getPackageManager().getPackageInfo("com.facebook.katana", 0).versionCode;
  } catch (PackageManager.NameNotFoundException e) {
    e.printStackTrace();
  }

  if (versionCode >= 3002850) {
    Uri uri = Uri.parse("fb://facewebmodal/f?href=" + "http://facebook.com/" + id);
    intent.setData(uri);
  } else {
    Uri uri = Uri.parse("fb://page/"+id);
    intent.setData(uri);
  }
}else{
  intent.setData( Uri.parse("http://facebook.com/" + id));
}

Facebookアプリを入れている場合は, そのバージョンのよってセットする Uri を分けているようです.

Twitter


Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_BROWSABLE);

if (AboutPageUtils.isAppInstalled(mContext, "com.twitter.android")){
  intent.setPackage("com.twitter.android");
  intent.setData(Uri.parse(String.format("twitter://user?user_id=%s",id)));
}else{
  intent.setData(Uri.parse(String.format("http://twitter.com/%s",id)));
}

Play Store


Uri uri = Uri.parse("market://details?id=" + id);
Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri);

YouTube


Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse(String.format("http://youtube.com/channel/%s", id)));

if (AboutPageUtils.isAppInstalled(mContext, "com.google.android.youtube")){
  intent.setPackage("com.google.android.youtube");
}

Instagram


Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://instagram.com/_u/"+id));

if (AboutPageUtils.isAppInstalled(mContext, "com.instagram.android")){
  intent.setPackage("com.instagram.android");
}

GitHub


Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.setData(Uri.parse(String.format("https://github.com/%s", id)));

まとめ

ユーザに, ブラウザで開くか, アプリで開くか, の選択の余地を与えず, インストールしているかの判断の後, パッケージ指定で独自スキームの Uri を渡して投げる, てのが今のやり方か.

それがおまえらのやり方か!!