DAY1の参加カンファレンス
1.マルチモジュールなプロジェクトでテストはどう変わるか
2.Unit test for ViewModel and LiveData
3.マテリアルデザインの起源とベースとなる哲学
4.FCMを使った用途に合わせたPush通知設計
5.Chrome Custom Tabsの仕組みから学ぶプロセス間通信
6.Androidエンジニアが抑えておくべきUnicode Emojiの知識
7.クロスプラットフォーム開発3種の神器 React Native / TypeScript / GraphQL
DAY1で参加はしていないが資料を確認したカンファレンス
8.Understanding Kotlin Coroutines: コルーチンで進化するアプリケーション開発
9.クロスプラットフォームモバイルアプリ開発ツール総ざらい2019 〜Titanium MobileからKotlin/Nativeまで〜
1.マルチモジュールなプロジェクトでテストはどう変わるか
マルチモジュールとは
アプリの実装を複数のモジュールに分ける。
切り出したモジュールはライブラリのように使える。
マルチモジュールでもテストの書き方は変わらない。
テスト方針の決め方
マルチモジュールに限った話ではないが、
ユニットテスト、ITテスト、UTテストがあるが
テストの仕方はプロダクトによって異なる。
組み合わせによって、プログラムの動作が網羅出来ていれば良い。
モジュールの設計時に考えることは
モジュールの責務とテストの範囲。
テスタビリティを意識して実装する。
テストメトリクス収集
PITというプラグインでコードを機械的に変更してテストしてくれる。
境界値チェックの不足がなくなる。
テスト結果はHTMLのレポートとして出力される。
マルチモジュールをテストする場合はモジュールごとにテスト結果が出るのでマージが必要。
2.Unit test for ViewModel and LiveData
MVVMアーキテクチャ
ViewとViewModelはLiveDataで繋がっている。
ViewModelはリポジトリを通してデータのやりとりをする。リポジトリにはLiveDataが乗っている。
リポジトリはコルーチンを使う。
ViewModelでリポジトリのインスタンスはコンストラクタで受け取る。
ViewModelのコルーチンのテスト
ViewModelのテストクラスで以下を記述
・リポジトリのモックインスタンスを作成
・テスト対象のViewModelのインスタンスを作成
・モックインスタンスのメソッドもモック化
・ViewModelのテスト対象のメソッドを実行
・モックインスタンスのメソッドが期待通り呼ばれたか検証する
delayなどの中断処理がテスト対象のメソッドの中にある場合、
最初の記述ではメソッドの終了を待てないので、元の実装でUnit(void)のところを
Jobを受け取るようにして、テスト実行時はJobをjoin()して中断関数にして処理を同期するようにする。
この時runBlockingを書かないといけない。
・コルーチンはメインスレッドで動くことを想定しているのでテストを実行すると落ちてしまう
メインスレッドで実行するように記述する
ViewModelのLiveDataのテスト
ViewModelのテストクラスで以下を記述
・Observerのモックを作成
・テスト対象のLiveDataを監視
・テスト対象のメソッドを実行
・期待通りの順でLiveDataが更新されたかを検証する
LiveDataに関してもメインスレッドで動くことを想定していてテスト時には落ちてしまう。
そうさせない方法がある。
テストしやすいのはどういう設計か
- ViewModelのコンストラクタでRepositoryのインスタンスを渡す。
依存するものはコンストラクタで定義するとテストし易い。 - ViewModelの分割を検討
画面1つにViewModel1つのイメージがあるが
ViewModelを分割してもよい、独立してきれいにわけれる場合は分割する。 - staticメソッドに切り出してテストをしやすくする
- 別メソッドやプロパティに切り出すことによってテストでモックに置き換えられるようにする
3.マテリアルデザインの起源とベースとなる哲学
マテリアルデザイン まとめ
・ユーザー体験としてわかりやすいもの(UI/UX)
・安定的なデザイン(紙とペンでポスターを書くように枯れた技術を使う)
・マテリアルデザインを使う上で他との差別化をするには色とかフォント
マテリアルデザインは社会や歴史とリンクしていて、非常に良く出来ている。
ユーザー体験としてわかりやすいもの
マテリアルデザインのルールは、脳にやさしい心踊る体験。
- 認知科学
子供は仮設と検証の繰り替えし理解する
大人は経験で理解する。
3歳でもパターン認識できることがある。
それは持っているりんごの手を離すとりんごが落ちる。
大人と同等に理解出来る。
光・面・動き(これらは3歳でも理解できる)
- 視覚野
運動のパターン認識に力を発揮する。
りんごが手を離す落ちること3歳の子供でも認識出来るが
下から上がってくると視覚野がいらっとする。
人は知識に反するものはわくわくする。
視覚野は裏切るといらっとするが、その他は、裏切るのは心踊る体験となる。
重要なのは
脳にやさしい体験
心踊る体験
を両立すること。
安定的なデザイン
枯れた印刷デザイン技術の活用。
紙とインクでポスターを書くように
枯れた技術を活用して安定したデザインを提供する。
マテリアルデザインを使う上で他との差別化をするには色とかフォント
マテリアルデザインは誰でも使えるパレットになって
どんなブランドでもベストに使える。
誰が使っても同じになるはずだが、会社が違えば異なるデザインになる。ここが重要で
多様性を提供できるインフラを求めてマティアスはマテリアルデザインに落としていった。
ベースはマテリアルデザインで、それで表現出来ない場合は、その他のデザインも取り入れることが出来る。
マテリアルデザインが生み出されるまでの歴史の変遷
生産性/合理性 vs 多様性/個性
18世紀中頃から上記の争いの変遷が現在に至るまである
18世紀中旬 産業革命
圧倒的生産性
↓
アーツアンドクラフト運動で生活の多様性
多様性/個性に偏っていく、バランスがだいぶくずれていく
↓
生産性/合理性への揺り戻し
↓
コストモダン
圧倒的な多様性/個性に偏ったものも現れる
生産性と多様性のバランスをどう取るか
現在はこの2つのバランスはとれている。
この歴史の変遷が今のマテリアルデザインにつながる。
誰が作ったか
マティアス・デュアルテ。
Googleのデザインの責任者。
この人が統括して作った。
この間マテリアルデザイン2が発表された。
4.FCMを使った用途に合わせたPush通知設計
プッシュ通知は様々な用途に使える
- 特定の個人や多数に送れる。
- トピックを使用することにより、あるトピックを購買したユーザだけがそのトピック専用のプッシュ通知を受け取ることができる。
- サーバサイドからの任意のタイミングでの送信の場合、配信時間が深夜にならないように気をつけないといけない。
- リアルタイム性のあるトピックを購買したユーザには、プッシュ通知をリアルタイムで送信する。
- 大量のユーザが購買するようなトピックでは、送信時に遅延の問題が発生してくる。送信処理バッチの並列化などで対応出来る。
- タイトルとメッセージをそのままアプリで表示するようにすれば、タイトルやメッセージが変更になる場合でも
サーバサイドの改修だけで、アプリは改修不要となる。 - AndroidのOSバージョンによっては、プッシュ通知に対応していないので
DBやログ(データのフィルタリングにはBigQuery)でユーザのOSバージョンを記録して
プッシュ通知が対応していない端末には通知を送らないようにする。
5.Chrome Custom Tabsの仕組みから学ぶプロセス間通信
Androidのプロセス間通信
・Intent
・AIDL
・Content Provider
・その他(Socket、ファイル共有etc)
今回取り上げるのはIntentとAIDL。
- Intent
通信先のアプリをPackageManagerのresolveServiceメソッドで探す。
通信先のアプリはAndroidManifestのintent-filterのactionで対象となるサービスを登録しておく。
ChromeCustomTabsではputExtraでよくデータを渡している。
Intentでは1MB以上の大きなデータは渡せない。
Intentではプリミティブ型とParcerable(インスタンスのバイト配列)が渡せる。
- AIDL
アプリとアプリのインターフェースなので密結合になりやすい、
一度リリースすると修正出来ないのでよく考えて作る。
AIDLで通信を行う為には、相手のプロセスが起動している必要がある。
起動していないと例外が出る。
IntentのputExtraで渡せないデータ1MBもAIDLでは渡せる。
AIDLでプリミティブ型・String・Parcelableとそれらを要素とするList・Mapを渡せる。
AIDLを経由した通信では、相手側のアプリ内のリソースを受け取ることも出来る。
6.Androidエンジニアが抑えておくべきUnicode Emojiの知識
Unicode Emojiの誕生
従来は各キャリアのSJIS外字領域に定義されていたが
Gmailの日本進出などのタイミングでUnicodeに定義されるようになった。
その際、すでにUnicodeに収録されていた記号と重複する絵文字はまとめられた。
iOSやAndroidもUnicode Emojiを利用している。
Emoji Presentation
絵文字にはPNGを使っているものと2次ベジエ曲線を使っているものの2パターンがある。
OSによって同じ絵文字でも色が赤だったりモノクロだったりする。
各絵文字はUnicodeに紐づいてEmoji_Presentationというフラグ
を持っていてYesならPNGを使う、Noならベジエ曲線の白黒のものを使うとなる。
OS・フォントによってデフォルトのEmoji_Presentaionが異なるため、異なる表示になる。
Emoji Sequence
複数の文字(Unicode)で一つの絵文字を構成する。
7.クロスプラットフォーム開発3種の神器 React Native / TypeScript / GraphQL
ReactNativeを用いる理由
工数を抑えるため
カンファレンスで紹介されたアプリ
結果として、ReactNativeとネイティブアプリのハイブリッドアプリになった。
既存のアプリ改修の際、新規画面の作成でReactNativeを用いた。
ReactNativeとは
Reactを用いる。ReactはJavaScriptのビューライブラリ。
AndroidとiOSのアプリを開発出来る。
ViewはRecyclerViewなどではなくReactのViewが使われる。
ネイティブの処理を呼び出すことが出来る。
作成する画面の分析
どこまでネイティブ、どこからReactNativeにするかを考える
→リストUIだけReactNativeにした。
リスト部分が様々なセルがまじっって高コスト。
リストはGraphQLと相性がいいのもあった。
画面遷移やビジネスロジックはネイティブの方で記述する。
ReactNativeその他
・ホットリロードなのでTry & Errorしやすい
・Androidのデバッグビルドが重い。iOSはそんなに重くない。
リリースビルドでは問題ない。
デバッグビルドは遅くてリリースビルドと違うので
パフォーマンスチューニングがすごく難しい。
・ReactNativeのバージョンのせいでAndroidStudioのバージョンを自由にあげられない。
・たまにクラッシュする。
8.Understanding Kotlin Coroutines: コルーチンで進化するアプリケーション開発
コルーチンの基本的な動作
GlobalScope.launchの中身がサブルーチンの中身と同じような扱い。
ただ、サブルーチンは一度呼び出したら終了するまで実行して途中から再開できないのに対して、
コルーチンは中断関数(delay()や自前のsuspendを関数)を呼び出したところで、その呼び出しまでは処理して
また別のタイミングで、次の処理から再開することが出来る。
コルーチンはシングルスレッドで動作するが、メインの処理をブロッキングすることなく
CPUをうまく利用して動作する。
CoroutineScope(Dispatchers.Defalult).launchはバックグラウンドのジョブを作成する。
CoroutineScope(Dispatchers.Unconfined).launchはメインスレッドのジョブを作成する。
val Job = GlobalScope.launch { // 戻り値はJob
// コルーチンの処理
}.join() または .await()
で呼び出し先のコルーチンの処理が終了するまで、ここで待つ。
また、join()やawait()で処理終了を待たないことも出来る。
job.cancel()で実行中のジョブをキャンセルすることも出来る。
続けてjob.join()を書くことで、中止処理の完了待ちをする。
コルーチンの並行実行
GlobalScope.launch {
val task1 = async { // 戻り値は Deferred<T>
delay(1000L)
return@async "1"
}
val task2 = async {
delay(1000L)
return@async "1"
}
}
この時task1とtask2は順序関係なく並行実行される。
CPUの利用について、複数のコルーチンで協調しCPUの資源を有効に活用する。
コルーチンはサスペンド関数のタイミングでのみ中断 asyncでサスペンド関数を囲うと非同期で処理する。
コルーチンは書いた処理を順次に評価して実行する点は変わらない。
launchブロックが中断可能な関数と通常のコードをつなぐ。
GlobalScope.launchでコルーチンの起動を行う。
アプリ開発においては通常、GrobalScopeは利用しない。
アプリ内のライフサイクルに基づいてCoroutineScopeを独自定義した方が良い。
val job = CoroutineScope(Dispatchers.Default).launch {
}
コルーチンを優先して処理させてメインの処理をブロッキング
次のようにrunBlockingで囲うと
コルーチンの処理をしている間はメインの処理をさせない。
サスペンド関数のテストで使える。
runBlocking {
targetViewModel.loadItemList().join()
}
coVerify(exactly = 1) { itemRepository.getItemList() } // runBlockingの処理が終わったら実行される
MVVMでのコルーチンの使い所
ViewModelでリポジトリを呼び出すところに
CoroutineScope.launch {
// リポジトリのサスペンド関数を呼び出す
}
リポジトリではサスペンド関数を作成して内部にDBアクセスやAPIアクセスの処理を書く。
9.クロスプラットフォームモバイルアプリ開発ツール総ざらい2019 〜Titanium MobileからKotlin/Nativeまで〜
クロスプラットフォーム=XPF
なぜXPF開発を行うか
予算が限られているから。
XPFツールだけどそれだけではない
各PFの「おまじない」や「お作法」が共通APIに実装済みなので
各PFで開発するよりも割と簡単に実装出来る。
・AndroidマンだけどReactNativeでiOS版が出来た。
・iOSガールだけどFlutterでAndroid版が出来た。
・AndroidマンだけどXamarinでAndroid版だけ作った。
XPFの歴史
-
Titanium Mobile by Appcelerator
流行年:2011年〜
JavaScriptでiOSとAndroidのアプリが作れる -
AIR for Mobile by Adobe
流行年:2012年〜
ActionScriptでiOSとAndroidのアプリが作れる
Adobe Flash系なので「UI独自描画方式」を採用 -
RubyMotion by Scratchwork
流行年:2013年〜
RubyでiOSとAndroidのアプリが作れる
iOSとAndroidのAPIがRubyから呼び出せるPFのAPIラッパを提供 -
Delphi/C++Builder by Embarcadero
流行年:2013年〜
Delphi/C++でiOSとAndroidのアプリが作れる
Adobe AIRと同じく「UI独自描画方式」を採用
iOSとAndroidのAPIのAPIラッパを提供 -
Tamarin by Microsoft
流行年:2016年〜
C#/.NETでiOSとAndroid、Win向けのアプリが作れる
AndroidとiOSのAPIのラッパに加え、.NET Frameworkの一部機能を共通APIとして提供
画面開発には、共通API(Xamarin.Forms)を提供 -
ReactNative by Facebook
流行年:2016年〜
React(JavaScriptのビューライブラリ)でiOSとAndroid、Win向けのアプリが作れる
共通APIと共通の画面定義(JSX)を提供
SkypeもReactNative製 -
Cordova by Apache
流行年:2017年〜
Web標準技術(HTML5+CSS+JavaScript)を使ってiOSやAndroidなどに対応したアプリを作れる
ネイティブアプリの中に簡易ブラウザWebViewを表示し、その中でWebアプリを動作させる
仕組みによって実現される -
Flutter by Google
流行年:2017年〜
DartでiOSとAndroidのアプリが作れる。Webはこれから
独自描画方式によりAndroidでもiOSでもマテリアルデザインに準拠したUIを提供。
iOS-styleのクパチーノもある
ホットリロードにより画面開発が速い -
Kotlin/Native with MPP by JetBrains
流行年:2018年〜
Kotlin/Native
KotlinからiOS(等の他PF)のAPIが使える
iOS/Android/Web等向けネイティブライブラリがビルド出来る
各PFでビルドしたファイルを組み込んで使う。
アプリを直接作ることも出来る。
MPP(Multi Platform Project)
共通APIを作る仕組みがある。共通APIではインターフェースを定義して
各PF毎に実装を行う。
XPF開発ツールの分類
- 画面描画方式による分類
- PFに移譲
プラットフォームのUIパーツが使用される - 独自描画
UIパーツをCanvasに自力で描画する
- API提供方式による分類
- PFのAPIラッパを提供しない
- PFのAPIラッパを提供する
RubyからActivityクラスが使える
KotlinからUIViewControllerが使える
PWA
PWAとはProgress Web Appsで、モバイル向けWebサイトをスマートフォン向け
アプリのように使える仕組み。
VS Webアプリ。
APIラッパがあるXPFツールでは、PFごとに作るよりも簡単に出来る。
XPFの開発言語とWebView内のJavaScriptとの連携は必須。