Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Amplify Flutter を使おうとしたけど微妙な結果に終わった話
Search
hmatsu47
PRO
November 26, 2021
Technology
1
5.1k
Amplify Flutter を使おうとしたけど微妙な結果に終わった話
JAWS-UG 浜松 AWS 勉強会 2021#11 2021/11/26
hmatsu47
PRO
November 26, 2021
Tweet
Share
More Decks by hmatsu47
See All by hmatsu47
Claude 3.5 で Haiku
hmatsu47
PRO
0
8
HeatWave on AWS の PrivateLink インバウンドレプリケーションで Aurora フェイルオーバーに追従する
hmatsu47
PRO
0
8
大吉祥寺.pm の LT で ChatGPT の力を借りて Next.js App Router ベースの投句箱を作って、 Lambda Web Adapter を使って公開した話
hmatsu47
PRO
0
8
ある日突然 DB の性能が 1/2(サイズのインスタンス相当)になった話
hmatsu47
PRO
0
30
pgvectorscale と pgai の話(ざっくり)
hmatsu47
PRO
0
49
pgvector 0.7.0 の新機能と、これから来る(かもしれない)pgvectorscale
hmatsu47
PRO
0
35
大人の社会科見学 ~ NTT 技術史料館に行ってみよう!
hmatsu47
PRO
0
420
pgvector 0.6.0 以降の進化についてざっくり取り上げてみる
hmatsu47
PRO
0
64
Cloudflare Workes からMySQL 系 DB への接続事情(2024/4 現在)
hmatsu47
PRO
0
130
Other Decks in Technology
See All in Technology
OCI Security サービス 概要
oracle4engineer
PRO
0
6.5k
DynamoDB でスロットリングが発生したとき/when_throttling_occurs_in_dynamodb_short
emiki
0
250
SREが投資するAIOps ~ペアーズにおけるLLM for Developerへの取り組み~
takumiogawa
1
380
Evangelismo técnico: ¿qué, cómo y por qué?
trishagee
0
360
OCI Network Firewall 概要
oracle4engineer
PRO
0
4.2k
rootlessコンテナのすゝめ - 研究室サーバーでもできる安全なコンテナ管理
kitsuya0828
3
390
OTelCol_TailSampling_and_SpanMetrics
gumamon
1
180
Zennのパフォーマンスモニタリングでやっていること
ryosukeigarashi
0
130
強いチームと開発生産性
onk
PRO
35
11k
AI前提のサービス運用ってなんだろう?
ryuichi1208
8
1.4k
ドメインの本質を掴む / Get the essence of the domain
sinsoku
2
160
Adopting Jetpack Compose in Your Existing Project - GDG DevFest Bangkok 2024
akexorcist
0
110
Featured
See All Featured
Being A Developer After 40
akosma
87
590k
Code Review Best Practice
trishagee
64
17k
Put a Button on it: Removing Barriers to Going Fast.
kastner
59
3.5k
Visualization
eitanlees
145
15k
Imperfection Machines: The Place of Print at Facebook
scottboms
265
13k
How To Stay Up To Date on Web Technology
chriscoyier
788
250k
GraphQLとの向き合い方2022年版
quramy
43
13k
How to Ace a Technical Interview
jacobian
276
23k
The Invisible Side of Design
smashingmag
298
50k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
GraphQLの誤解/rethinking-graphql
sonatard
67
10k
We Have a Design System, Now What?
morganepeng
50
7.2k
Transcript
Amplify Flutter を使おうとしたけれど 微妙な結果に終わった話 JAWS-UG 浜松 AWS 勉強会 2021#11 2021/11/26 まつひさ(hmatsu47)
自己紹介 松久裕保(@hmatsu47) https://qiita.com/hmatsu47 名古屋で Web インフラのお守り係をしています (ほかに書くことがなくなったので省略) 2
おことわり • ここに書いた内容は私が実際に試した時点の情報です ◦ 2021/05 〜 2021/10 頃の話です ◦ その後
Amplify CLI のバージョンアップが入っているので、すで に解消されている問題があるかもしれません ◦ 実際、最初に書いた「iOS で DataStore のレコード削除をすると 落ちる」問題はその後解消されていました 3
Flutter を試そうと思ったきっかけ • 以前 Qiita でバズったこのサイト ◦ https://korette.jp/ 4
Flutter を試そうと思ったきっかけ • 以前 Qiita でバズったこのサイト ◦ https://korette.jp/ ◦ サポーターズの一員として大量にクイズ投稿
5
Flutter を試そうと思ったきっかけ • 以前 Qiita でバズったこのサイト ◦ https://korette.jp/ ◦ サポーターズの一員として大量にクイズ投稿
◦ その後、コロナ禍で観光地の状況が一変 ◦ コロナが落ち着いた隙をみながら問題メンテナンスの旅へ 6
Flutter を試そうと思ったきっかけ • 以前 Qiita でバズったこのサイト ◦ https://korette.jp/ ◦ サポーターズの一員として大量にクイズ投稿
◦ その後、コロナ禍で観光地の状況が一変 ◦ コロナが落ち着いた隙をみながら問題メンテナンスの旅へ ◦ 旅のお供として、情報収集・整理のためのアプリが欲しい ◦ 作ることにした 7
余談ですが • ご本人は起業されて・・・ ◦ https://ambirise.jp/ 8
Amplify Flutter を試そうと思った動機 • 普通に考えたら Firebase ◦ Flutter も Google
謹製 9
Amplify Flutter を試そうと思った動機 • 普通に考えたら Firebase ◦ Flutter も Google
謹製 ◦ ありがちで面白くない ◦ どうせなら普段使っている AWS で 10
Amplify Flutter を試してみた • まずはチュートリアルから(英語版) ◦ https://docs.amplify.aws/start/getting-started/installation/q/integration/flutter/ ◦ Android で
DataStore を使った DynamoDB 同期が成功 ◦ iOS ではなぜかレコード削除で落ちる 11
Amplify Flutter を試してみた • まずはチュートリアルから(英語版) ◦ https://docs.amplify.aws/start/getting-started/installation/q/integration/flutter/ ◦ Android で
DataStore を使った DynamoDB 同期が成功 ◦ iOS ではなぜかレコード削除で落ちる ◦ しばらく放置 12
その後 • AWS へのデータ同期は一旦置いて、 ◦ アプリ本体の開発に着手 ◦ https://github.com/hmatsu47/maptool ◦ ローカルへのデータ保存に
SQLite(sqflite)を使用 13
その後 • AWS へのデータ同期は一旦置いて、 ◦ アプリ本体の開発に着手 ◦ https://github.com/hmatsu47/maptool ◦ ローカルへのデータ保存に
SQLite(sqflite)を使用 ◦ ある程度骨格ができたところで、まずは DataStore を導入 ◦ 問題発覚 14
自動生成されたデータモデルがエラーに • 原因は Null Safety ◦ Flutter 2.0 で導入されたもの ▪
この時点ではエラーにはならず ◦ Flutter 2.2 以降で非 Null Safety なデータモデルはエラーに ▪ 仕方なく温かみのある手作業で修正 15
自動生成されたデータモデルがエラーに • 原因は Null Safety ◦ Flutter 2.0 で導入されたもの ▪
この時点ではエラーにはならず ◦ Flutter 2.2 以降で非 Null Safety なデータモデルはエラーに ▪ 仕方なく温かみのある手作業で修正 ◦ ほどなくして Amplify CLI のバージョンアップ通知が ▪ バージョンアップでエラーは解消(ワーニング多くて気持ち悪いけど) 16
自動生成されたデータモデルがエラーに • 原因は Null Safety ◦ Flutter 2.0 で導入されたもの ▪
この時点ではエラーにはならず ◦ Flutter 2.2 以降で非 Null Safety なデータモデルはエラーに ▪ 仕方なく温かみのある手作業で修正 ◦ ほどなくして Amplify CLI のバージョンアップ通知が ▪ バージョンアップでエラーは解消(ワーニング多くて気持ち悪いけど) ◦ そして事件が発生 17
SQLite のテーブルが消失😱 • DataStore のローカルデータ保存 : SQLite を使用 ◦ アプリで実装している
DB は DataStore のローカルストアが 初期化される都度、巻き添えをくらって削除される 18
SQLite のテーブルが消失😱 • DataStore のローカルデータ保存 : SQLite を使用 ◦ アプリで実装している
DB は DataStore のローカルストアが 初期化される都度、巻き添えをくらって削除される ◦ たまたまコピーしてあった SQLite のファイルからローカル DB を復活させた ◦ DataStore 使うなら別のローカル DB を使うこともないか・・・ 19
SQLite のテーブルが消失😱 • DataStore のローカルデータ保存 : SQLite を使用 ◦ アプリで実装している
DB は DataStore のローカルストアが 初期化される都度、巻き添えをくらって削除される ◦ たまたまコピーしてあった SQLite のファイルからローカル DB を復活させた ◦ DataStore 使うなら別のローカル DB を使うこともないか・・・ ◦ しかし 20
DynamoDB に同期されないテーブルがある • 3 つあるテーブルのうち最も単純なものを除いて NG ◦ 試しにテーブルを 1 つにしても
NG 21
DynamoDB に同期されないテーブルがある • 3 つあるテーブルのうち最も単純なものを除いて NG ◦ 試しにテーブルを 1 つにしても
NG ◦ ローカルの SQLite には正しく保存される ◦ AppSync で AWS に送っている形跡はある(ログより) ◦ でもテーブルには同期されない ▪ 「失敗した」ログは出てくれない 22
DynamoDB に同期されないテーブルがある • 3 つあるテーブルのうち最も単純なものを除いて NG ◦ 試しにテーブルを 1 つにしても
NG ◦ ローカルの SQLite には正しく保存される ◦ AppSync で AWS に送っている形跡はある(ログより) ◦ でもテーブルには同期されない ▪ 「失敗した」ログは出てくれない 23
DynamoDB に同期されないテーブルがある • 3 つあるテーブルのうち最も単純なものを除いて NG ◦ 試しにテーブルを 1 つにしても
NG ◦ ローカルの SQLite には正しく保存される ◦ AppSync で AWS に送っている形跡はある(ログより) ◦ でもテーブルには同期されない ▪ 「失敗した」ログは出てくれない 24
DynamoDB に同期されないテーブルがある • 3 つあるテーブルのうち最も単純なものを除いて NG ◦ 試しにテーブルを 1 つにしても
NG ◦ ローカルの SQLite には正しく保存される ◦ AppSync で AWS に送っている形跡はある(ログより) ◦ でもテーブルには同期されない ▪ 「失敗した」ログは出てくれない 25
DynamoDB に同期されないテーブルがある • 3 つあるテーブルのうち最も単純なものを除いて NG ◦ 試しにテーブルを 1 つにしても
NG ◦ ローカルの SQLite には正しく保存される ◦ AppSync で AWS に送っている形跡はある(ログより) ◦ でもテーブルには同期されない ▪ 「失敗した」ログは出てくれない ◦ 諦めた 26
REST API に変えてみた • CLI で amplify add api して
REST を選んで・・・ ◦ API Gateway 経由で Node.js の DynamoDB 保存用 Lambda を 使ってチャレンジ→失敗 ▪ JavaScript 版の Amplify ではうまく行くのに・・・ 27
REST API に変えてみた • CLI で amplify add api して
REST を選んで・・・ ◦ API Gateway 経由で Node.js の DynamoDB 保存用 Lambda を 使ってチャレンジ→失敗 ▪ JavaScript 版の Amplify ではうまく行くのに・・・ ◦ Lambda の環境変数名と Node.js に書かれた環境変数を参照して いる部分の記述がなぜか違う ▪ REGION と TABLE_REGION(なお、直しても動かず) 28
REST API に変えてみた • CLI で amplify add api して
REST を選んで・・・ ◦ API Gateway 経由で Node.js の DynamoDB 保存用 Lambda を 使ってチャレンジ→失敗 ▪ JavaScript 版の Amplify ではうまく行くのに・・・ ◦ Lambda の環境変数名と Node.js に書かれた環境変数を参照して いる部分の記述がなぜか違う ▪ REGION と TABLE_REGION(なお、直しても動かず) ◦ 諦めた 29
結局、 • API Gateway & Lambda Python で回避 ◦ これ↓を参考に
https://business.ntt-east.co.jp/content/cloudsolution/column-try-20.html ◦ コード的には RESTful ではなくなったけどヨシ!! ▪ パスパラメータなし ▪ 全部 POST ◦ クライアント側だけ Amplify Flutter のライブラリを使用 30
結局、 • API Gateway & Lambda Python で回避 ◦ これ↓を参考に
https://business.ntt-east.co.jp/content/cloudsolution/column-try-20.html ◦ コード的には RESTful ではなくなったけどヨシ!! ▪ パスパラメータなし ▪ 全部 POST ◦ クライアント側だけ Amplify Flutter のライブラリを使用 31 // バックアップ情報を登録 Future<bool> backupSet( AmplifyClass amplify, String backupTitle, String describe) async { try { final RestOptions options = RestOptions( path: '/backupsets', body: const Utf8Encoder() .convert(('{"OperationType": "PUT", "Keys": {"items": [' ' {"title": ${jsonEncode(backupTitle)}' ', "describe": ${jsonEncode(describe)}}' ']}}'))); final RestOperation restOperation = amplify.API.post(restOptions: options); await restOperation.response; // ignore: avoid_print print('POST call (/backupsets) succeeded'); return true; } on ApiException catch (e) { // ignore: avoid_print print('POST call (/backupsets) failed: $e'); return false; } }
結局、 • API Gateway & Lambda Python で回避 ◦ これ↓を参考に
https://business.ntt-east.co.jp/content/cloudsolution/column-try-20.html ◦ コード的には RESTful ではなくなったけどヨシ!! ▪ パスパラメータなし ▪ 全部 POST ◦ クライアント側だけ Amplify Flutter のライブラリを使用 32 // バックアップ情報リストを AWS から取得 Future<List<BackupSet>> fetchBackupSets(AmplifyClass amplify) async { final List<BackupSet> resultList = []; try { final RestOptions options = RestOptions( path: '/backupsets', body: const Utf8Encoder().convert(('{"OperationType": "SCAN"}'))); final RestOperation restOperation = amplify.API.post(restOptions: options); final RestResponse response = await restOperation.response; final Map<String, dynamic> body = json.decode(response.body); final List<dynamic> items = body['Items']; for (dynamic item in items) { resultList.add(BackupSet(item['title'] as String, item['describe'])); } resultList.sort((a, b) => b.title.compareTo(a.title)); // ignore: avoid_print print('POST call (/backupsets) succeeded'); } catch (e) { // ignore: avoid_print print('POST call (/backupsets) failed: $e'); } return resultList; }
S3 も・・・ • 個人で使うアプリにわざわざ Cognito を入れたくない ◦ Amplify Flutter では
Storage(S3)だけ API KEY 認証がない ▪ 面倒臭い ◦ MinIO の非公式クライアント(minio)で回避 ▪ Amplify はどこへ・・・? 33
S3 も・・・ • 個人で使うアプリにわざわざ Cognito を入れたくない ◦ Amplify Flutter では
Storage(S3)だけ API KEY 認証がない ▪ 面倒臭い ◦ MinIO の非公式クライアント(minio)で回避 ▪ Amplify はどこへ・・・? 34 // 画像ファイルを S3 アップロード _uploadS3( Minio minio, Picture picture, String imagePath, String s3Bucket) async { final int pathIndexOf = picture.filePath.lastIndexOf('/'); final String fileName = (pathIndexOf == -1 ? picture.filePath : picture.filePath.substring(pathIndexOf + 1)); final String filePath = '$imagePath/$fileName'; try { await minio.fPutObject(s3Bucket, fileName, filePath); // ignore: avoid_print print('S3 upload $fileName succeeded'); return fileName; } catch (e) { // ignore: avoid_print print('S3 upload $fileName failed: $e'); return false; } }
トドメ • 距離計測と絡めてデータを取得したい ◦ DynamoDB ではできない ◦ DocumentDB は最近できるようになったようだけど高い ◦
PostGIS 使いたい 35
トドメ • 距離計測と絡めてデータを取得したい ◦ DynamoDB ではできない ◦ DocumentDB は最近できるようになったようだけど高い ◦
PostGIS 使いたい ◦ Supabase 使えばいいじゃん、PostgREST 使えるし https://supabase.com/ ▪ Amplify はどこへ・・・?(2 回目) 36
トドメ • 距離計測と絡めてデータを取得したい ◦ DynamoDB ではできない ◦ DocumentDB は最近できるようになったようだけど高い ◦
PostGIS 使いたい ◦ Supabase 使えばいいじゃん、PostgREST 使えるし https://supabase.com/ ▪ Amplify はどこへ・・・?(2 回目) 37 Future<List<SpotData>> searchNearSpot( SupabaseClient client, LatLng latLng, int distLimit) async { final PostgrestResponse selectResponse = await client.rpc('get_spots', params: { 'point_latitude': latLng.latitude, 'point_longitude': latLng.longitude, 'dist_limit': distLimit }).execute(); final List<dynamic> items = selectResponse.data; final List<SpotData> resultList = []; for (dynamic item in items) { final SpotData spotData = SpotData( item['distance'] as num, item['category_name'] as String, item['title'] as String, item['describe'] as String, LatLng((item['latitude'] as num).toDouble(), (item['longitude'] as num).toDouble()), PrefMuni(item['prefecture'] as String, item['municipality'] as String)); resultList.add(spotData); } return resultList; }
まとめ • Amplify : 頻出構成を最速で作るためのもの ◦ 自分専用の個人開発アプリとはユースケースが合わなくて当然 ◦ ユースケースが合わないものに対して無理に使うと、かえって 開発がつらくなる
◦ Flutter 以外の環境と比較するとまだ開発途上→うまく使えなく ても仕方がない 38
おまけ • 作っているアプリ(maptool) 39 Google Maps Platform ではなく Mapbox の地図を使用
←訪問(予定)先にピンを立てて、ピンに関連づけて写真撮影
おまけ • 作っているアプリ(maptool) 40 ←地図スタイル切り替え可
おまけ • 作っているアプリ(maptool) 41 ←地図スタイル切り替え可
おまけ 42 • 作っているアプリ(maptool)
おまけ 43 • 作っているアプリ(maptool) ←10km 以内にあるスポットを表示 (ほかにもいくつか機能あり)
おまけ 44 • 関連ブログ記事 ◦ https://qiita.com/hmatsu47/items/b98ef4c1a87cc0ec415d ◦ https://zenn.dev/hmatsu47/articles/846c3186f5b4fe ◦ https://zenn.dev/hmatsu47/articles/9102fb79a99a98
◦ https://zenn.dev/hmatsu47/articles/e81bf3c2bf00f8 ◦ https://qiita.com/hmatsu47/items/e4f7e310e88376d54009 ◦ https://qiita.com/hmatsu47/items/86a9c028bb5b3beeebdd ◦ https://qiita.com/hmatsu47/items/53ea68769c4fc2d76450