7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Flutter & Firestore で気軽に永続化してオラオラする方法

Last updated at Posted at 2021-01-10

スクリーンショット 2021-01-10 17.39.18.png

🧑‍💻 まえがき

■やること

  • Flutter & Firebase Firestore にて、必要最低限の実装内容で動くものを作成

■作業概要

  • STEP0:事前準備、参考資料
  • STEP1:firebaseの設定
  • STEP2:設定ファイルの配置
  • STEP3:パッケージの追加
  • STEP4:接続テスト
  • STEP5:firestoreの準備
  • STEP6:コードの実装

■下記の症状に効能があります

  • flutter & firestore の日本語資料がない
  • 公式教材やってみたけど、バージョンが古くて動かない
  • もっと気軽に普段からオラオラできたら便利
  • てめぇは俺を怒らせた

■環境

  • editer:VScode
  • flutter:1.22.5
  • Dart:2.10.4
  • xcode:12

📗STEP0:事前準備、参考資料

🔥STEP1:firebaseの設定

■appプロジェクト作る

  • 先にappのプロジェクトを作成すること
  • プロジェクト作成
    • flutter create sampleApp
  • シュミレーター起動
    • open -a Simulator
  • projectの起動
cd flutter_sample
flutter run

■firebaseの設定

  • コンソール画面で「プロジェクトを追加」
  • アナリティクスの設定は適当でok!

スクリーンショット 2021-01-10 11.29.25.png

📃STEP2:設定ファイルの配置(iOS)

  • 下記からiosとandroidの設定をそれぞれ追加

スクリーンショット 2021-01-10 11.31.15.png

  • バンドルIDをxcodeで確認して入力

スクリーンショット 2021-01-10 11.34.22.png
スクリーンショット 2021-01-10 11.59.46.png

  • GoogleService-Info.plistをダウンロード
  • plistを**"xcodeから"**pjの"Runner/Runnerディレクトリ"に追加する
  • その時、表示されるダイアログでcopyにチェックが入ってることを必ずチェック(私はこれではまった)

スクリーンショット 2021-01-10 11.39.15.png

スクリーンショット 2021-01-10 11.39.59.png

  • ファイルの追加を行ったら、firebaseのios設定画面STEP3と4はスキップでok
    スクリーンショット 2021-01-10 12.00.42.png
    *もともとxcodeでの追加設定前提の内容なので、ファイル追加以降の操作は不要

📚STEP3:パッケージの追加

dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^0.5.3 ←追加
  firebase_analytics: ^6.3.0 ←追加
  cloud_firestore: ^0.14.4 ←追加

スクリーンショット 2021-01-10 12.36.34.png

✅STEP4:接続テスト

  • デフォルトのmain.dartに下記のように追記
main.dart
import 'package:flutter/material.dart';
import 'package:firebase_analytics/firebase_analytics.dart'; //←追加
import 'package:firebase_analytics/observer.dart'; //←追加

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  static FirebaseAnalytics analytics = FirebaseAnalytics(); //←追加
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
      //↓追加
      navigatorObservers: [
        FirebaseAnalyticsObserver(analytics: analytics),
      ],
    );
  }
}
  • flutter runを実行(*runするとpluginが自動でinstallされる&podfileも更新される)
  • firebase→dashboardを確認
  • 下記のように「過去30分間のユーザー」に反応があれば接続成功

スクリーンショット 2021-01-10 14.04.18.png

🗄STEP5:firestoreの準備

■DB作成

  • コンソールからClound Firestore > データベースの作成を選択
    スクリーンショット 2021-01-10 16.39.41.png

  • テストモードを選択
    スクリーンショット 2021-01-10 17.22.54.png

  • 地域はasia-northeast1(東京)を選択
    スクリーンショット 2021-01-10 17.24.27.png

■サンプルデータを作成

  • コレクション(sqlで言うところのテーブル名)を設定
    スクリーンショット 2021-01-10 17.28.01.png
  • ドキュメント(sqlで言うところのレコード)を作成
  • (IDは自動IDを選択すると自動で振ってくれます)
    スクリーンショット 2021-01-10 17.28.47.png
  • 作成後はこんな感じ
    スクリーンショット 2021-01-10 17.28.55.png

🧑‍💻STEP6:コードの実装

  • main.dartを下記に変更
main.dart

import 'package:flutter/material.dart';
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:firebase_analytics/observer.dart';
import 'package:cloud_firestore/cloud_firestore.dart'; //←追加
import 'package:firebase_core/firebase_core.dart'; //←追加

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  static FirebaseAnalytics analytics = FirebaseAnalytics();
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(title: 'やれやれだぜ'),
      navigatorObservers: [
        FirebaseAnalyticsObserver(analytics: analytics),
      ],
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: _buildBody(),
    );
  }

  Widget _buildBody() {
    final Future<FirebaseApp> _initialization = Firebase.initializeApp();
    return FutureBuilder(
      future: _initialization,
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          return _streamBuilder();
        }
        return LinearProgressIndicator();
      },
    );
  }

  Widget _streamBuilder() {
    return StreamBuilder<QuerySnapshot>(
      stream: FirebaseFirestore.instance.collection('rushes').snapshots(),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (!snapshot.hasData) {
          return LinearProgressIndicator();
        }
        return _buildList(snapshot.data.docs);
      },
    );
  }

  Widget _buildList(List<DocumentSnapshot> snapshot) {
    return ListView(
      padding: const EdgeInsets.only(top: 20.0),
      children: snapshot.map((data) {
        return _buildListItem(data);
      }).toList(),
    );
  }

  Widget _buildListItem(DocumentSnapshot data) {
    final rushes = Rushes(data);

    return Padding(
      padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
      child: Container(
        decoration: BoxDecoration(
          border: Border.all(color: Colors.grey),
          borderRadius: BorderRadius.circular(6.0),
        ),
        child: ListTile(
            title: Text(rushes.makeOraOra()),
            trailing: FlatButton(
              onPressed: () {
                rushes.reference.update({'times': 0});
              },
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Icon(
                    Icons.delete,
                  ),
                  Text(rushes.times.toString()),
                ],
              ),
            ),
            onTap: () {
              rushes.reference.update({'times': FieldValue.increment(1)});
            }),
      ),
    );
  }
}

class Rushes {
  String word;
  int times;
  DocumentReference reference;

  Rushes(DocumentSnapshot snapshot) {
    var map = snapshot.data();
    this.word = map['word'];
    this.times = map['times'];
    this.reference = snapshot.reference;
  }

  String makeOraOra() {
    var ret = "";
    for (var i = 0; i < times; i++) {
      ret += word;
    }
    return ret;
  }
}

🎊🤸‍🎉Congratulations!🎉🤸‍🎊

完成したら、いいね!&コメントに「ワッフルワッフル」と叫んでください😆✨
スクリーンショット 2021-01-10 17.39.18.png

📱サンプルはこちら📱

💾 https://github.com/TD3P/flutter_rushMaker

🌟ご指摘大歓迎🌟

ここちゃうで!!っていうとこあったら、教えてもらえると嬉しいです!!

シリーズ情報

📱Flutterで基本のTODOアプリを作ってみよう
https://qiita.com/pe-ta/items/b3b7458059c1fd7efcf0

📱Flutterでページ遷移するTODOアプリを作ってみよう
https://qiita.com/pe-ta/items/e547c4cf460319f5093c

📱Flutter x Firestore で気軽に永続化してオラオラする方法
https://qiita.com/pe-ta/items/ccd49fc396b063a821af

7
6
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
7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?