Flutter×FirebaseのAuthとCRUD処理まとめ
M1 MacBook、Android Studio、Flutter 2.0
2021年1月末からプログラミング学習始めた初心者です。自分用メモ。
https://qiita.com/igakeso/items/2c567176326f783801d6
前回、Flutter×FirebaseのCRUD処理をまとめたのですが、Authのuidと紐付いていないことに気付いたため、FrebaseAuthのuidと共通でFirestoreにusersのcollectionを作り、そのサブコレクションにtodoのcollectionを作り、サブコレクションに対してCRUDを行う処理をまとめました。
1、FlutterとFIrebaseのセットアップ
https://firebase.google.com/docs/flutter/setup
2、セットアップ後、main.dartだけで動くコードです。
firebase_core: ^1.3.0
firebase_auth: ^1.4.1
cloud_firestore: ^2.2.2
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Auth CRUD',
theme: ThemeData(
backgroundColor: Colors.blue,
),
home: AuthPage(),
);
}
}
class AuthPage extends StatefulWidget {
@override
_AuthPageState createState() => _AuthPageState();
}
class _AuthPageState extends State<AuthPage> {
late TextEditingController nameInputController = TextEditingController();
late TextEditingController emailInputController = TextEditingController();
late TextEditingController passwordInputController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('ログイン画面'),
),
body: Center(
child: Container(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.network(
'https://1.bp.blogspot.com/-UG7cj_zxYes/X4aVsGG-tgI/AAAAAAABbys/BpJ8aaXO6vALEcBTUJtPzo-0sBQaOT69wCNcBGAsYHQ/s862/ofuro_sauna_door.png',
height: 200.0),
TextFormField(
controller: nameInputController,
decoration: const InputDecoration(labelText: 'お名前(初回登録時のみ入力)'),
),
TextFormField(
controller: emailInputController,
decoration: const InputDecoration(labelText: 'メールアドレス'),
keyboardType: TextInputType.emailAddress,
),
TextFormField(
controller: passwordInputController,
decoration: const InputDecoration(labelText: 'パスワード(6文字以上)'),
obscureText: true,
),
const SizedBox(height: 20),
Container(
width: double.infinity,
child: ElevatedButton(
child: const Text('ユーザー登録'),
onPressed: () async {
try {
await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: emailInputController.text,
password: passwordInputController.text);
await FirebaseFirestore.instance.collection("users").doc(FirebaseAuth.instance.currentUser!.uid).set({
'name': nameInputController.text,
'email': emailInputController.text,
});
} catch (e) {
print(e);
}
},
),
),
const SizedBox(height: 10),
Container(
width: double.infinity,
child: ElevatedButton(
child: const Text('ログイン'),
onPressed: () async {
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: emailInputController.text,
password: passwordInputController.text);
final loginUser = FirebaseAuth.instance.currentUser;
await FirebaseFirestore.instance.collection("users").doc(loginUser!.uid).get();
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => HomePage(loginUser)));
} catch (e) {
print(e);
}
},
),
),
],
),
),
),
);
}
}
class HomePage extends StatefulWidget {
HomePage(this.loginUser);
late User loginUser;
@override
_HomePageState createState() => _HomePageState(loginUser);
}
class _HomePageState extends State<HomePage> {
_HomePageState(this.loginUser);
User loginUser;
TextEditingController createTodoController = TextEditingController();
TextEditingController updateTodoController = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('ログイン後画面'),
),
body: SafeArea(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: Text('Login User uid: ' + loginUser.uid),
),
Image.network('https://1.bp.blogspot.com/-f3RpEHd25R4/X79cj7SEo_I/AAAAAAABce8/tPhWRoxKbOAvUNRcwqxK1YmVyKrKCNapwCNcBGAsYHQ/s762/ofuro_sauna_gaikiyoku.png',
height: 200.0),
Container(
child: Expanded(
child: StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection('users').doc(loginUser.uid).collection('todo').snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemBuilder: (BuildContext context, int index) {
return CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
title: Text(snapshot.data!.docs[index]['title']),
value: snapshot.data!.docs[index]['isDone'],
onChanged: (value) {
snapshot.data!.docs[index].reference.update({
'isDone': value,
'updatedTime': Timestamp.now(),
});
},
secondary: IconButton(
icon: const Icon(Icons.more_horiz),
onPressed: () {
showModalBottomSheet(
context: context,
builder: (context) {
return SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
title: const Text('編集'),
leading: const Icon(Icons.edit),
onTap: () {
Navigator.pop(context);
showDialog(
context: context,
builder: (context) {
return SimpleDialog(
title: Container(
child: Column(
children: [
const Text('編集'),
Container(
child: TextField(
controller: updateTodoController,
decoration: const InputDecoration(
border: OutlineInputBorder()
),
),
),
ElevatedButton(
onPressed:
() async {
await snapshot.data!.docs[index].reference.update({
'title': updateTodoController.text,
'updatedTime': Timestamp.now(),
});
Navigator.pop(context);
},
child: const Text('編集'),
)
],
),
),
);
});
},
),
ListTile(
title: const Text('削除'),
leading: const Icon(Icons.delete),
onTap: () {
Navigator.pop(context);
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(
'${snapshot.data!.docs[index]['title']}を削除実行しますか?'
),
actions: [
TextButton(
onPressed:
() async {
await snapshot.data!.docs[index].reference.delete();
Navigator.pop(context);
},
child: const Text('削除実行'),
),
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('キャンセル'),
),
],
);
});
},
)
],
),
);
});
},
),
);
},
itemCount: snapshot.data!.docs.length,
);
} else {
return Container();
}
}),
),
),
Container(
padding: const EdgeInsets.only(left: 20, right:20),
width: double.infinity,
child: ElevatedButton(
child: const Text('ログアウト'),
onPressed: () async {
await FirebaseAuth.instance.signOut();
Navigator.of(context).pop();
}),
),
],
),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
showModalBottomSheet(
context: context,
builder: (context) {
return SafeArea(
child: Column(mainAxisSize: MainAxisSize.min, children: [
const Padding(
padding: EdgeInsets.all(10.0),
child: Text('ToDo新規登録'),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Text('Login User uid: ' + loginUser.uid),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
child: TextField(
controller: createTodoController,
decoration: const InputDecoration(
border: OutlineInputBorder()
),
),
),
),
Container(
padding: const EdgeInsets.only(left:20, right:20),
width: double.infinity,
child: ElevatedButton(
child: const Text('新規登録'),
onPressed: () async {
await FirebaseFirestore.instance.collection("users").doc(loginUser.uid).collection('todo').add({
'title': createTodoController.text,
'isDone': false,
'createdTime': Timestamp.now()
});
Navigator.pop(context);
},
),
),
Container(
width: double.infinity,
padding: const EdgeInsets.only(left:20, right:20),
child: ElevatedButton(
child: const Text('戻る'),
onPressed: () {
Navigator.of(context).pop();
},
),
),
]
),
);
});
}),
);
}
}
Author And Source
この問題について(Flutter×FirebaseのAuthとCRUD処理まとめ), 我々は、より多くの情報をここで見つけました https://qiita.com/igakeso/items/d9a3d734946b8dd8a0bf著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .