【Flutter】get_itとcloud_firestoreで、Firebase Cloud Firestoreのデータを更新する
Flutter

【Flutter】get_itとcloud_firestoreで、Firebase Cloud Firestoreのデータを更新する

作成日:2022年04月18日
更新日:2022年04月18日

前回は、Flutter のパッケージである get_it と cloud_firestore を使い、Firebase のデータベースにデータを削除しました。

flutter-get_it-cloud_firebase-delete

【Flutter】get_itとcloud_firestoreで、Firebase Cloud Firestoreのデータを削除する

今回は、Firebase Cloud Firestore のデータを更新します。

firebase のコードは、前回までのコードを使用します。

dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class FirebaseService {
FirebaseAuth _auth = FirebaseAuth.instance;
FirebaseFirestore _database = FirebaseFirestore.instance;
FirebaseService();
Future<bool> registerUser({
required String email,
required String password,
}) async {
try {
UserCredential _userCredential = await _auth
.createUserWithEmailAndPassword(email: email, password: password);
return true;
} catch (e) {
print(e);
return false;
}
}
Future<bool> loginUser({
required String email,
required String password,
}) async {
try {
UserCredential _userCredential = await _auth.signInWithEmailAndPassword(
email: email, password: password);
if (_userCredential.user != null) {
return true;
} else {
return false;
}
} catch (e) {
print(e);
return false;
}
}
Stream<QuerySnapshot> getBooks() {
return _database
.collection('books')
.orderBy('timestamp', descending: true)
.snapshots();
}
Future<bool> postBook({required String title, String? author}) async {
try {
await _database.collection('books').add(
{
'title': title,
'author': author,
'timestamp': Timestamp.now(),
},
);
return true;
} catch (e) {
print(e);
return false;
}
}
Future<bool> deleteBook({required String docId}) async {
try {
await _database.collection('books').doc(docId).delete();
return true;
} catch (e) {
print(e);
return false;
}
}
}

まずは、Cloud Firestore の単一データを取得するために、getBookを作成します。

単一データを取得するには、docにドキュメント ID を指定します。

dart
Stream<DocumentSnapshot<Map<String, dynamic>>> getBook(String docId) {
return _database.collection('books').doc(docId).snapshots();
}

次に、Cloud Firestore のデータを更新するために、updateBookを作成します。

データを更新するには、updateを設定します。

dart
Future<bool> updateBook(
{required String docId, String? title, String? author}) async {
try {
await _database.collection('books').doc(docId).update(
{
'title': title,
'author': author,
},
);
return true;
} catch (e) {
print(e);
return false;
}
}

次に、更新画面を作成します。

dart
import 'package:flutter/material.dart';
class UpdateBook extends StatefulWidget {
UpdateBook({Key? key}) : super(key: key);
State<UpdateBook> createState() => _UpdateBookState();
}
class _UpdateBookState extends State<UpdateBook> {
double? _deviceWidth, _deviceHeight;
final GlobalKey<FormState> _updateBookKey = GlobalKey<FormState>();
String? _title;
String? _author;
Widget build(BuildContext context) {
_deviceWidth = MediaQuery.of(context).size.width;
_deviceHeight = MediaQuery.of(context).size.height;
return Scaffold(
body: SafeArea(
child: Container(
padding: EdgeInsets.symmetric(
horizontal: _deviceWidth! * 0.05,
),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Text(
'書籍編集',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
Container(
height: _deviceHeight! * 0.2,
child: Form(
key: _updateBookKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextFormField(
decoration: const InputDecoration(hintText: 'タイトル'),
onSaved: (_value) {
setState(() {
_title = _value!;
});
},
),
TextFormField(
decoration: const InputDecoration(hintText: '著者'),
onSaved: (_value) {
setState(() {
_author = _value;
});
},
),
],
),
),
),
MaterialButton(
onPressed: () {},
minWidth: _deviceWidth! * 0.5,
height: _deviceHeight! * 0.06,
color: Colors.blueAccent,
child: const Text(
'更新',
style: TextStyle(
color: Colors.white, fontWeight: FontWeight.bold),
),
)
],
),
),
),
),
);
}
}

初期画面で指定した書籍を表示するために、controllerを設定します。

dart
class _UpdateBookState extends State<UpdateBook> {
double? _deviceWidth, _deviceHeight;
FirebaseService? _firebaseService;
final GlobalKey<FormState> _updateBookKey = GlobalKey<FormState>();
String? _title;
String? _author;
TextEditingController _titleController = TextEditingController();
TextEditingController _authorController = TextEditingController();

TextFormFieldcontrollerを指定します。

dart
TextFormField(
controller: _titleController,
decoration:
const InputDecoration(hintText: 'タイトル'),
onSaved: (_value) {
setState(() {
_title = _value!;
});
},
),
TextFormField(
controller: _authorController,
decoration:
const InputDecoration(hintText: '著者'),
onSaved: (_value) {
setState(() {
_author = _value;
});
},
),
],

get_itfirebase_serviceをインポートします。

dart
import 'package:get_it/get_it.dart';
import 'package:test_form/services/firebase_service.dart';

FirebaseService の変数を作成します。

dart
class _LoginState extends State<Login> {
double? _deviceWidth, _deviceHeight;
FirebaseService? _firebaseService;

initStateを作成し、GetItgetFirebaseServiceを呼び出します。

dart
void initState() {
super.initState();
_firebaseService = GetIt.instance.get<FirebaseService>();
}

一覧を作成するために、StreamBuilderを設定します。

streamは、_firebaseServicegetBook()を指定します。

builderは、contextsnapshotを設定します。

snapshotdataが存在する場合は一覧を表示し、存在しない場合はインジケータを表示します。

他画面から遷移する場合、getBook内の『'LznyXT6qZyflKSvkgZ4z'』は、ドキュメント ID を指定するといいでしょう。

dart
child: Container(
padding: EdgeInsets.symmetric(
horizontal: _deviceWidth! * 0.05,
),
child: Center(
child: StreamBuilder(
stream: _firebaseService!.getBook('LznyXT6qZyflKSvkgZ4z'),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Text(
'書籍編集',
style: TextStyle(
fontSize: 24, fontWeight: FontWeight.bold),
),
Container(
height: _deviceHeight! * 0.2,
child: Form(
key: _updateBookKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextFormField(
controller: _titleController,
decoration:
const InputDecoration(hintText: 'タイトル'),
onSaved: (_value) {
setState(() {
_title = _value!;
});
},
),
TextFormField(
controller: _authorController,
decoration:
const InputDecoration(hintText: '著者'),
onSaved: (_value) {
setState(() {
_author = _value;
});
},
),
],
),
),
),
MaterialButton(
onPressed: (){},
minWidth: _deviceWidth! * 0.5,
height: _deviceHeight! * 0.06,
color: Colors.blueAccent,
child: const Text(
'更新',
style: TextStyle(
color: Colors.white, fontWeight: FontWeight.bold),
),
)
],
);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
),
),

_titleController.textsnapshot.data?['title']_authorController.textsnapshot.data?['author']を指定します。

それぞれ、データがなければ、空データが入るようにします。

dart
child: StreamBuilder(
stream: _firebaseService!.getBook('LznyXT6qZyflKSvkgZ4z'),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
_titleController.text = snapshot.data?['title'] != null
? snapshot.data['title']
: '';
_authorController.text = snapshot.data?['author'] != null
? snapshot.data['author']
: '';

最後に、更新ボタンを機能させるために、_update関数を作成します。

先ほど作成したupdateBookを使用します。

updateBookには、ドキュメント ID と_title_authorを渡すようにします。

dart
void _update(
docId,
) async {
_updateBookKey.currentState!.save();
bool _result = await _firebaseService!
.updateBook(docId: docId!, title: _title, author: _author);
print('更新結果: $_result');
}

MaterialButtononPressed_updateを設定します。

dart
MaterialButton(
onPressed: () => _update('LznyXT6qZyflKSvkgZ4z'),
minWidth: _deviceWidth! * 0.5,
height: _deviceHeight! * 0.06,
color: Colors.blueAccent,
child: const Text(
'更新',
style: TextStyle(
color: Colors.white, fontWeight: FontWeight.bold),
),
)

では、動作確認します。

画面を確認すると、

image2

image3

getBookで指定した単一データが表示されました。

では、タイトルを編集して、更新ボタンをタップしてみます。

image4

image5

更新結果:ture が返ってきました。

Firebase の Cloud Firestore を確認すると、

image6

titleが更新されていました。

© 2024あずきぱんウェブスタジオ