☕
Flutterでゆるいアプリ新規開発するぞってときにやること備忘録
なにこれ
- なんか軽いアプリ作りたいなって思ったときにササッとFlutterで作る流れをまとめました
- アーキテクチャは最低限のView-Logic-Domainが分かれてれば良いやろという方針です (あくまでゆるいアプリをササッと作ることを目的にしてるので)
- 割と我流なのでちょくちょくブラッシュアップするかもです
前提
- AndroidStudio,Xcodeインストール済
- Flutter開発環境構築済
- New Flutter AppのデフォルトのカウントAppが動作している状態
やっていき
コーヒーを淹れます ☕️
- すべてのはじまり
- まずはテンション上げてこ ↑↑
依存追加
- 作るアプリに必要なもの入れればいいと思います
- とりあえずView-Logicで分けるだけしたいのでRiverpodだけ入れます
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
flutter_riverpod: ^2.0.0-dev.9
フォルダ構成
- ここも開発環境やプレイ人数に合わせて対応すればいいと思います
- アプリによっては
main.dart
単体もありそうですね (規模感や将来性との兼ね合い) - とりあえず自分は画面ごと+otherとかで分ければいいじゃんという気持ちです
- ~/lib
- data
- data_source
- (repository)
- ui
- conponents
- scene_1
- (ui)
- (logic)
- scene_2
...
テンプレ
-
Provider
周りはFlutter Architecture Blueprintsを参考にしました🙏
共通部分
main.dart
- 命名は
main.dart
じゃなくてもいいですがとりあえず・・・ -
ProviderScope
で囲んでます
import 'package:my_app/scenes/home/HomeScene.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/all.dart';
void main() {
runApp(ProviderScope(child: MainApp()));
}
class MainApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: "appName",
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: FirstScene());
}
}
各画面
FirstScene.dart
-
StatelessWidget
として切り分けて画面管理させてます - 画面そのものは
StatelessWidget
、描画担当はConsumerWidget
を使ってます
import 'package:flutter/material.dart';
import 'FirstSceneWidget.dart';
class FirstScene extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("first")), body: FirstSceneWidget());
}
}
FirstSceneWidget.dart
- 描画担当です
-
ConsumerWidget
を継承させて、Riverpod
のwatch()
でViewModelを監視するようにしてます - 思うがままにレイアウトを構築しましょう
- ViewModelの処理を呼ぶテンプレを書きたかったので
GestureDetector
でタップ可能にしてます
import 'package:my_app/scenes/home/HomeViewModel.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class FirstSceneWidget extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final _viewModel = ref.watch(firstProvider);
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTap: () {
_viewModel.cntUp();
},
child: Text(_viewModel.text,
style: Theme.of(context).textTheme.headline4))
],
));
}
}
FirstViewModel.dart
-
ChangeNotifier
を継承させてるのでViewに対して値を通知する前提で実装してます -
firstProvider
として定義しておくことで各面で呼ぶだけでインスタンス化できるようにします - 今回は簡単なカウントアップの処理を書いてます
Domainは?
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
final firstProvider = ChangeNotifierProvider((ref) => FirstViewModel());
class FirstViewModel extends ChangeNotifier {
var _cnt = 0;
var text = "0";
void cntUp() {
_cnt++;
text = _cnt.toString();
notifyListeners();
}
}
この後
- これで一つの画面ができました
- この後はRepositoryクラスを作って
FirstViewModel
のようにproviderを経由させて呼んだり、はたまた同じように新しい画面を作ったりするのも良いと思います
おわり
- 軽いアプリならさっと作れるやんって感じてくれたら嬉しいです
- クラスを使い回すのが簡単なのでちゃんと制限をかけて実装していくことが大事ですね
(基本ですがProviderで処理を切り分けた上で必要な値以外はprivateにしてアクセスできなくするなど)
Discussion