Flutter

FlutterのTestでCallbackをモックする

FlutterのTestでCallbackをmockitoでモックする FlutterのテストでChangeNotifierのサブクラスのaddListenerに渡したCallbackが呼ばれたかテストしたい場合に、ダミーのコールバックでフラグを立ててフラグをexpectで検査することがある。 これをmockitoを使ってverifyで検証する方法がある。 返値がVoidのモックまず以下のmixin(もしくはclassでも可)を作成する。 mixin Callback<T> { T call(); } callメソッドを持ったクラスは関数のようにcallメソッドを呼ぶことができるようになる。例えば以下のように。 class A { void call() { print('a'); } } final a = A(); a(); // a.call()が実行されaが出力される 次にmockitoのGenerateMocksアノテーションで、CallbackからCallbackのモックを作成する。以下を記述してbuild_runner

WidgetTestでGoRouterでの画面遷移をモックする

Widget TestでGoRouterのモックを利用するにはInheritedGoRouter WidegtをWidgetツリーに組み込むと良いのですが、GoRouterライブラリではInheritedGoRouterはexportされておらず、利用できませんでした。 ということでFlutter PackagesのIssueとPRを作成してGoRouterに取り込んでもらいました。 すでにリリースされているので、Widget Testでは以下のようにGoRouterのモックを組み込むことができます。 testWidgets('mediates Widget\'s access to GoRouter.', (WidgetTester tester) async { final MockGoRouter router = MockGoRouter(); await tester.pumpWidget(MaterialApp( home: InheritedGoRouter(goRouter: router,

宣言的UIフレームワークのアーキテクチャパターン考察

この記事では宣言的UIにどのアーキテクチャパターンが良いかを述べるのではなく、宣言的UIでのアーキテクチャパターンの課題とアドバイスを記しています。 概論私はiOSネイティブアプリのプログラマでした。現在でも個人ではSwiftUIでアプリを作成していますが、業務ではFlutterアプリを作成しています。ですのでAndroidネイティブのことはわからないのでiOSとFlutterを主に話題にします。 iOSのUIKitではMVCが標準のアーキテクチャパターンでした。一方SwiftUIやFlutterは標準のアーキテクチャパターンが存在しません。存在しないとどうなるのでしょうか。去年私が引き継いだFlutterプロジェクトが、存在しない場合の最悪な実装を示してくれました。 簡単に述べると「WidgetがAPIアクセスを行い、JSONから子Widgetが生成され表示する」という実装です。当然Widgetは肥大化してスパゲッティコードになっていました。 UIKitではMVCのCが肥大化する問題が注目されていますが、標準アーキテクチャパターンが存在することで少なくともVとCは分離され、Vの見通しはある程度良い状態が保たれていました。 React Nativeは詳しくないのですがReactと同様にReduxが一般的のようで、Reduxに乗ってしまえば設計に関して問題は発生しにくいと言えます。 しかしSwiftUIやFlutterでは上記のようなVにすべてを載せてしまう実装まですでに発生しているのです。この2つのフレームワークではアーキテクチャパターンによる設計を十分検討して適用する必要があると言えます。 MVSwiftUIやFlutterではMVで良い、という意見をよく目にします。 VがMを購読Vがビジネスロジックの起動を依頼という構造です。この構造、どこかで見たと思いませんか?そう、MVCです。AppleのMVCはCがMとVの仲立ちをするのですが、非AppleのMVCでは上記のような構造になっています。

iOS Simulatorの操作中にVSCodeにショートカットキーを送る

iOS Simulatorの操作中にVSCodeにショートカットキーを送る FlutterアプリをiOS Simulatorで操作中にHot Restartなどを行うにはVisual Studio Codeをアクティブにして操作する必要がある。 iOS Simulatorがアクティブな状態でHot Restartを行うにはVSCodeにキーイベントを送信すると可能になる。 Keyboard Maestroを使うと簡単に仕組みを作ることができる。 Keyboard Maestroのマクログループを作成作成したグループにAvailable in these applicationsとしてSimulatorをセットグループ内にマクロを作成Hot Key Trigger(もしくは何らかのTrigger)を指定ActionとしてType a Keystrokeを追加Simulate keystrokeにVSCodeのHot Restartのショートカットキーを指定アクションのギアアイコンをクリックしてSend ToにCode(VSCodeはCodeという名前で表示される)を指定これによりiOS SimulatorがアクティブなときにショートカットキーでVSCodeでHot Restartが実行できる。

FlutterのAmplifyでS3にファイルをアップロードするとフォルダにPrefixがつく

FlutterのAmplifyでS3にファイルをアップロードするとフォルダにPrefixをつけられてしまう FlutterでAWS S3にファイルをアップロードするためにprachiFam/amazon_s3_cognitoというライブラリを利用していた。 しかしこのライブラリでは最新のFlutterでAndroid向けにビルドできない問題があり、AWSの公式ライブラリであるaws-amplify/amplify-flutterに乗り換えようとした。 amplifyコマンドでauthとstorageをimport。amplifyライブラリを組み込みセットアップを完了。アップロードは成功した。しかしサービスのサーバ側がファイルを認識しない。S3のbucketを開いてもファイルは無い…と思ったら実はpublic/アップロードで指定したkeyとしてファイルがアップロードされていた。 実はAmplifyライブラリを利用すると自動的にフォルダにprefixが付与され、アクセス権限ごとに別フォルダになるようになっていた。amplify-flutterが内部で利用するiOSやAndroidのライブラリでは設定でprefixを変更できるように修正済みのようだが、Flutterのライブラリは追随できていないようだ。 Feature Request: Support the use of custom storage paths · Issue #416 · aws-amplify/amplify-flutter回避する方法はなさそうなので、