Flutterを使ってみた感想
こんにちは、インです。グロービスで学習サービスを作っているエンジニアです。1年ぐらいFlutterを使ってきたので、その感想、起こりやすいミスや解決Tipsなどをまとめました。
使ってみた感想
生産性が高い
静的型付け言語Dartで開発するので、リファクタリングする時やlibrary、frameworkの内部実装を確認する時に非常に効率的です。もちろん、強力な型推論があるので、毎回、型を明示的に宣言する必要がありません。
Hot reload、Hot restart機能があるので、書いたコードが直ぐ画面で反映できます。
豊富なWidgetがあるので、自分でUIを実装する時間を節約できます。
学習コストが低い
Dartの文法がシンプルでわかりやすいので、プログラミング経験があれば、一日ぐらいで勉強できます。
公式サイトにドキュメントが充実しています。
この一年でflutterに関する記事が爆発的なスピードで出てきて、トラブルシューティングも楽です。
楽しい
ユーザーが使う機能を効率的に開発でき、素早く価値を提供できるので、楽しいです。
注意点やTipsなど
UI Debug方法
Flutter Inspectorを使うと便利です。Web版の場合、テキストの選択、コピー、ページ内の検索に弱い
テキストはデフォルトで選択、コピーできないという制限があります。
これについては、SelectableText, SelectableHtml widgetを使って改善できます。ただwidgetに跨って選択することができません。この点については2022年のroadmapに上がってるので、改善が期待できると思います。状態管理を間違うと無限buildになる可能性がある
影響:
1. clientが死ぬ
2. backendが超負荷になる
3. 想定外の課金につながる
例えば、以下のコードのような場合、build処理の状態で、watchと同時に更新を行うと、無限にbuildが実行されます。回避方法:build処理がトリガーになった状態で更新をしない
final counter = StateProvider((ref) => 1);
class Screen extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final x = ref.watch(counter);
WidgetsBinding.instance?.addPostFrameCallback((_) {
ref.read(s.notifier).state = ref.read(s.notifier).state + 1;
});
.....
Webアプリでcookieが使えない時の対応方法
cross site通信でcookieを使いたい場合は、withCredentialsをtrueにする必要があります。
withCredentialsに関する詳細は https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials を参考にすることをおすすめします。
var dio = Dio();
if (dio.httpClientAdapter is BrowserHttpClientAdapter) {
(dio.httpClientAdapter as BrowserHttpClientAdapter).withCredentials = true;
}
webアプリで外部ファイルjavascriptを呼ぶ場合、javascriptのloadが遅くて、NoSuchMethodErrorエラーになる問題
解消案
1. javascriptが自作の場合、index.htmlのinline scriptで書く
2. javascriptを別ファイルにする場合、コードで動的にloadして、load完了後にflutterのmain.dart.jsをloadする
javascriptをコードで動的にloadするサンプルコード:
function loadScript(url, callback) {
var scriptTag = document.createElement("script")
scriptTag.type = "text/javascript";
scriptTag.onload = function() {
callback()
};
scriptTag.src = url;
document.body.append(scriptTag);
}
function loadMainDartJs() {
if (scriptLoaded) {
return;
}
scriptLoaded = true;
loadScript("https://code.jquery.com/jquery-3.6.0.min.js", function() {
var scriptTag = document.createElement('script');
scriptTag.src = 'main.dart.js';
scriptTag.type = 'application/javascript';
document.body.append(scriptTag);
});
}
画像表示が失敗する可能性があるので、errorBuilderを必ず指定する
loadが遅いときは、loadingBuilderも提供して、ユーザーのストレスを軽減しましょう。
Image.network(url, errorBuilder: (_, __, ___) => Text("画像の表示が失敗しました"))
Hiveを使うときに、boxをcloseすることを忘れないようにする
webアプリを作成するときにboxをcloseしないと、別のTABを開くときにboxに設定した値が取れない現象が発生します。例えば、認証情報をhiveで管理するときに、ログインしても、別のTABでは未ログイン状態のままになります。
Webアプリの場合、rendererはHTML vs CanvasKit?
選択の判断で参考できる情報
1. https://docs.flutter.dev/development/tools/web-renderers#choosing-which-option-to-use
2.日本語の表示問題
・https://zenn.dev/kboy/articles/4b00eae424c991
・https://zenn.dev/inari_sushio/articles/ce9b3fb220fa15Sentry上のエラーのstack traceが役に立たない問題
リリースするとき、sentryにsource mapsをアップロードしましょう。
webアプリで直URL指定しても、ページが開けるようにする
riverpodなどで状態管理をするときに、直URLでページを開くときもページで使う状態を正常に設定するように工夫しないと、ページが表示できない可能性があります。
webアプリの場合、本番公開前にweb/index.html中の自動生成されたmeta 、titleタグを更新しておく
自動生成されたコードは以下のような感じです。
<meta name="description" content="A new Flutter project."><!-- iOS meta tags & icons -->
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="apple-mobile-web-app-title" content="untitled">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<title>untitled</title>
Htmlをflutter中で表示する方法
Htmlをflutter中で表示することで既にあるhtmlコンテンツを活用することができます。slideshareの表示をコードで説明します
Widget build(BuildContext context) {
var url = 'https://www.slideshare.net/DataReportal/slideshelf';
final viewTypeId = 'slide.share:$url'; // 唯一にすることが大事
// ignore: undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(
viewTypeId,
(int viewId) => IFrameElement() // html elementを生成
..allow = 'fullscreen'
..width = '100%'
..height = '100%'
..src = url);
// HtmlElementViewを使ってhtml elementを表示
return SizedBox(
width: 760,
height: 570,
child: HtmlElementView(viewType: viewTypeId));
}
以上になりますが、少しでも皆さんに参考になれば幸いです。
2022年8月29日 19時~
教育ビジネス×Flutter開発の勉強会を開催いたします!
ご参加をお待ちしております。