0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Flutter/Bloc/Firestoreを用いた開発プロセス

Posted at

はじめに

私がアプリを個人開発する中で、どのようなプロセスで開発を進めているか備忘録的な意味を込めて残しておこうと思います。

開発環境

言語:Dart
フレームワーク:Flutter
アーキテクチャ:Bloc
DB:Firestore

ディレクトリ構成

下記はlib配下のディレクトリ構成です。
主要なディレクトリを抜き出しています。

.
├── blocs
│   ├── hoge_bloc.dart
├── main.dart
├── models
│   ├── hoge_model.dart
├── repositories
│   ├── hoge_repository.dart
└── screens
    └── hoge_screen.dart

開発プロセス

1: DB設計を行う
まずはDBにどのようなデータを保存するか設計します。
イメージしたDBを元にFirestoreにコレクションとドキュメントのダミーデータを入れておきます。

2: modelの作成
設計を元にmodelを作成します。

hoge_model.dart
class HogeModel {
  HogeModel({
    required this.fuga,
  });
  
  final int fuga;

  factory HogeModel.fromDocument(DocumentSnapshot<Object?> doc) {
    final Map<String, dynamic> data = doc.data() as Map<String, dynamic>;
    return HogeModel(
      fuga: data['fuga'],
    );
  }

  Map<String, dynamic> toMap() {
    return <String, dynamic>{
      'fuga': fuga,
    };
  }
}

3: repositoryの作成
firestore↔BlocをつなぐためのAPIを作成します。
API作成時点でfirestoreとの接続確認を行っておくと良いと思います。

hoge_repository.dart
class HogeRepository {
  final FirebaseFirestore _firestore = FirebaseFirestore.instance;

  Future<void> addFuga(String fuga) async {
    await _firestore.collection('fugaCollection').add(fuga.toMap());
  }

  Future<String?> fetchFuga() async {
    final fugaDoc = await _firestore.collection('fugaCollection').doc('fugaDoc').get();
    if (fugaDoc.exists) {
      return HogeModel.fromDocument(fugaDoc);
    }
    return null;
  }
}

4: blocの作成
Bloc↔screenをつなぐためのBlocを作成します。

hoge_bloc.dart
class HogeBloc extends Bloc<HogeEvent, HogeState> {
  HogeBloc() : super(HogeState()) {
    on<HogeEventFuga>((
      HogeEventFuga event,
      Emitter<HogeState> emit,
    ) async {
      _hogeRepository.addFuga(
        event.fuga,
      );
    });
  }

  final HogeRepository _hogeRepository = HogeRepository();
}

5: screenの作成
画面を作成します。

hoge_screen.dart
class HogePage extends StatelessWidget {
  const HogePage({super.key});

  @override
  Widget build(BuildContext context) {
    return BlocProvider<HogeBloc>(
      create: (BuildContext context) => HogeBloc(),
      child: const HogeScreen(),
    );
  }
}

class HogeScreen extends StatelessWidget {
  const HogeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          'Hoge Screen',
        ),
      ),
      body: BlocBuilder<HogeBloc, HogeState>(
        builder: (BuildContext context, HogeState state) {
          return TextButton(
            child: const Text('button'),
            onPressed: () {
              context
                  .read<HogeBloc>()
                  .add(HogeEventFuga('piyo'));
            },
          );
        },
      ),
    );  
  }
}

最後に

私が紹介したのはデータの依存関係にしたがって依存元から実装していくやり方です。
逆にUIから実装していくのもありだと思います。
参考になる部分があれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?