Cloud Firestore ODM使ってみた!
以前から興味あったので使って見ました!
今回もSoftware developerのKosukeさんの記事を参考にさせていただきました。
こちらが公式ドキュメント
Firebaseにプロジェクトをつくる。
今回はFirebase CLIを使ってiOS、Android、Web3つの環境を用意しました。
こちらを参考にしながら、環境構築していきます。
必要なパッケージを追加していく。追加し終わったのがこの状態
pubspec.yaml
name: odm_app
description: A new Flutter project.
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.0.0+1
environment:
sdk: ">=2.17.3 <3.0.0"
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
firebase_core: ^1.20.0
cloud_firestore: ^3.4.3
cloud_firestore_odm: ^1.0.0-dev.25
json_annotation: ^4.6.0
dev_dependencies:
flutter_test:
sdk: flutter
# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^2.0.0
build_runner: ^2.2.0
cloud_firestore_odm_generator: ^1.0.0-dev.25
json_serializable: ^6.3.1
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter packages.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages
今回はファイルが少ないのでこんな感じになっております。
モデルとなるファイルを作ります。Freezedより簡単かもしれないです?
でも、これ結構曲者で設定が必要みたいですね🤔
コードの保管機能で出てくるコードも違う?
今回は、ドキュメントのコードにTimestmp型を追加して見ました!
Timestmpを使うときは、Datetime型に変換する必要があります。出ないと人間には見ずらい表示になってしまう。
モデルとなるuser.dartを作成します。[part 'user.g.dart';]というコードは、ファイルと同じ名前でないといけません。コードを書いたら、ターミナルでコマンドを実行します。成功したらファイルが自動生成されます。
user.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:cloud_firestore_odm/cloud_firestore_odm.dart';
// This doesn't exist yet...! See "Next Steps"
part 'user.g.dart';
(explicitToJson: true)
class User {
User({
required this.name,
required this.age,
required this.email,
this.createdAt // ?つけてるので、requiredいらない!
});
final String name;
final int age;
final String email;
// TimestampConverter()と書くらしいがコードの保管機能で出てこなかった!
()
Timestamp? createdAt;
}
<User>('users')
final usersRef = UserCollectionReference();
こちらのコマンドを実行する
flutter pub run build_runner build --delete-conflicting-outputs
user.g.dart
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'user.dart';
// **************************************************************************
// CollectionGenerator
// **************************************************************************
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides
class _Sentinel {
const _Sentinel();
}
const _sentinel = _Sentinel();
/// A collection reference object can be used for adding documents,
/// getting document references, and querying for documents
/// (using the methods inherited from Query).
abstract class UserCollectionReference
implements
UserQuery,
FirestoreCollectionReference<User, UserQuerySnapshot> {
factory UserCollectionReference([
FirebaseFirestore? firestore,
]) = _$UserCollectionReference;
static User fromFirestore(
DocumentSnapshot<Map<String, Object?>> snapshot,
SnapshotOptions? options,
) {
return _$UserFromJson(snapshot.data()!);
}
static Map<String, Object?> toFirestore(
User value,
SetOptions? options,
) {
return _$UserToJson(value);
}
CollectionReference<User> get reference;
UserDocumentReference doc([String? id]);
/// Add a new document to this collection with the specified data,
/// assigning it a document ID automatically.
Future<UserDocumentReference> add(User value);
}
class _$UserCollectionReference extends _$UserQuery
implements UserCollectionReference {
factory _$UserCollectionReference([FirebaseFirestore? firestore]) {
firestore ??= FirebaseFirestore.instance;
return _$UserCollectionReference._(
firestore.collection('users').withConverter(
fromFirestore: UserCollectionReference.fromFirestore,
toFirestore: UserCollectionReference.toFirestore,
),
);
}
_$UserCollectionReference._(
CollectionReference<User> reference,
) : super(reference, reference);
String get path => reference.path;
CollectionReference<User> get reference =>
super.reference as CollectionReference<User>;
UserDocumentReference doc([String? id]) {
assert(
id == null || id.split('/').length == 1,
'The document ID cannot be from a different collection',
);
return UserDocumentReference(
reference.doc(id),
);
}
Future<UserDocumentReference> add(User value) {
return reference.add(value).then((ref) => UserDocumentReference(ref));
}
bool operator ==(Object other) {
return other is _$UserCollectionReference &&
other.runtimeType == runtimeType &&
other.reference == reference;
}
int get hashCode => Object.hash(runtimeType, reference);
}
abstract class UserDocumentReference
extends FirestoreDocumentReference<User, UserDocumentSnapshot> {
factory UserDocumentReference(DocumentReference<User> reference) =
_$UserDocumentReference;
DocumentReference<User> get reference;
/// A reference to the [UserCollectionReference] containing this document.
UserCollectionReference get parent {
return _$UserCollectionReference(reference.firestore);
}
Stream<UserDocumentSnapshot> snapshots();
Future<UserDocumentSnapshot> get([GetOptions? options]);
Future<void> delete();
Future<void> update({
String name,
int age,
String email,
Timestamp? createdAt,
});
Future<void> set(User value);
}
class _$UserDocumentReference
extends FirestoreDocumentReference<User, UserDocumentSnapshot>
implements UserDocumentReference {
_$UserDocumentReference(this.reference);
final DocumentReference<User> reference;
/// A reference to the [UserCollectionReference] containing this document.
UserCollectionReference get parent {
return _$UserCollectionReference(reference.firestore);
}
Stream<UserDocumentSnapshot> snapshots() {
return reference.snapshots().map((snapshot) {
return UserDocumentSnapshot._(
snapshot,
snapshot.data(),
);
});
}
Future<UserDocumentSnapshot> get([GetOptions? options]) {
return reference.get(options).then((snapshot) {
return UserDocumentSnapshot._(
snapshot,
snapshot.data(),
);
});
}
Future<void> delete() {
return reference.delete();
}
Future<void> update({
Object? name = _sentinel,
Object? age = _sentinel,
Object? email = _sentinel,
Object? createdAt = _sentinel,
}) async {
final json = {
if (name != _sentinel) "name": name as String,
if (age != _sentinel) "age": age as int,
if (email != _sentinel) "email": email as String,
if (createdAt != _sentinel) "createdAt": createdAt as Timestamp?,
};
return reference.update(json);
}
Future<void> set(User value) {
return reference.set(value);
}
bool operator ==(Object other) {
return other is UserDocumentReference &&
other.runtimeType == runtimeType &&
other.parent == parent &&
other.id == id;
}
int get hashCode => Object.hash(runtimeType, parent, id);
}
class UserDocumentSnapshot extends FirestoreDocumentSnapshot<User> {
UserDocumentSnapshot._(
this.snapshot,
this.data,
);
final DocumentSnapshot<User> snapshot;
UserDocumentReference get reference {
return UserDocumentReference(
snapshot.reference,
);
}
final User? data;
}
abstract class UserQuery implements QueryReference<User, UserQuerySnapshot> {
UserQuery limit(int limit);
UserQuery limitToLast(int limit);
/// Perform an order query based on a [FieldPath].
///
/// This method is considered unsafe as it does check that the field path
/// maps to a valid property or that parameters such as [isEqualTo] receive
/// a value of the correct type.
///
/// If possible, instead use the more explicit variant of order queries:
///
/// **AVOID**:
/// ```dart
/// collection.orderByFieldPath(
/// FieldPath.fromString('title'),
/// startAt: 'title',
/// );
/// ```
///
/// **PREFER**:
/// ```dart
/// collection.orderByTitle(startAt: 'title');
/// ```
UserQuery orderByFieldPath(
FieldPath fieldPath, {
bool descending = false,
Object? startAt,
Object? startAfter,
Object? endAt,
Object? endBefore,
UserDocumentSnapshot? startAtDocument,
UserDocumentSnapshot? endAtDocument,
UserDocumentSnapshot? endBeforeDocument,
UserDocumentSnapshot? startAfterDocument,
});
/// Perform a where query based on a [FieldPath].
///
/// This method is considered unsafe as it does check that the field path
/// maps to a valid property or that parameters such as [isEqualTo] receive
/// a value of the correct type.
///
/// If possible, instead use the more explicit variant of where queries:
///
/// **AVOID**:
/// ```dart
/// collection.whereFieldPath(FieldPath.fromString('title'), isEqualTo: 'title');
/// ```
///
/// **PREFER**:
/// ```dart
/// collection.whereTitle(isEqualTo: 'title');
/// ```
UserQuery whereFieldPath(
FieldPath fieldPath, {
Object? isEqualTo,
Object? isNotEqualTo,
Object? isLessThan,
Object? isLessThanOrEqualTo,
Object? isGreaterThan,
Object? isGreaterThanOrEqualTo,
Object? arrayContains,
List<Object?>? arrayContainsAny,
List<Object?>? whereIn,
List<Object?>? whereNotIn,
bool? isNull,
});
UserQuery whereDocumentId({
String? isEqualTo,
String? isNotEqualTo,
String? isLessThan,
String? isLessThanOrEqualTo,
String? isGreaterThan,
String? isGreaterThanOrEqualTo,
bool? isNull,
List<String>? whereIn,
List<String>? whereNotIn,
});
UserQuery whereName({
String? isEqualTo,
String? isNotEqualTo,
String? isLessThan,
String? isLessThanOrEqualTo,
String? isGreaterThan,
String? isGreaterThanOrEqualTo,
bool? isNull,
List<String>? whereIn,
List<String>? whereNotIn,
});
UserQuery whereAge({
int? isEqualTo,
int? isNotEqualTo,
int? isLessThan,
int? isLessThanOrEqualTo,
int? isGreaterThan,
int? isGreaterThanOrEqualTo,
bool? isNull,
List<int>? whereIn,
List<int>? whereNotIn,
});
UserQuery whereEmail({
String? isEqualTo,
String? isNotEqualTo,
String? isLessThan,
String? isLessThanOrEqualTo,
String? isGreaterThan,
String? isGreaterThanOrEqualTo,
bool? isNull,
List<String>? whereIn,
List<String>? whereNotIn,
});
UserQuery whereCreatedAt({
Timestamp? isEqualTo,
Timestamp? isNotEqualTo,
Timestamp? isLessThan,
Timestamp? isLessThanOrEqualTo,
Timestamp? isGreaterThan,
Timestamp? isGreaterThanOrEqualTo,
bool? isNull,
List<Timestamp?>? whereIn,
List<Timestamp?>? whereNotIn,
});
UserQuery orderByDocumentId({
bool descending = false,
String startAt,
String startAfter,
String endAt,
String endBefore,
UserDocumentSnapshot? startAtDocument,
UserDocumentSnapshot? endAtDocument,
UserDocumentSnapshot? endBeforeDocument,
UserDocumentSnapshot? startAfterDocument,
});
UserQuery orderByName({
bool descending = false,
String startAt,
String startAfter,
String endAt,
String endBefore,
UserDocumentSnapshot? startAtDocument,
UserDocumentSnapshot? endAtDocument,
UserDocumentSnapshot? endBeforeDocument,
UserDocumentSnapshot? startAfterDocument,
});
UserQuery orderByAge({
bool descending = false,
int startAt,
int startAfter,
int endAt,
int endBefore,
UserDocumentSnapshot? startAtDocument,
UserDocumentSnapshot? endAtDocument,
UserDocumentSnapshot? endBeforeDocument,
UserDocumentSnapshot? startAfterDocument,
});
UserQuery orderByEmail({
bool descending = false,
String startAt,
String startAfter,
String endAt,
String endBefore,
UserDocumentSnapshot? startAtDocument,
UserDocumentSnapshot? endAtDocument,
UserDocumentSnapshot? endBeforeDocument,
UserDocumentSnapshot? startAfterDocument,
});
UserQuery orderByCreatedAt({
bool descending = false,
Timestamp? startAt,
Timestamp? startAfter,
Timestamp? endAt,
Timestamp? endBefore,
UserDocumentSnapshot? startAtDocument,
UserDocumentSnapshot? endAtDocument,
UserDocumentSnapshot? endBeforeDocument,
UserDocumentSnapshot? startAfterDocument,
});
}
class _$UserQuery extends QueryReference<User, UserQuerySnapshot>
implements UserQuery {
_$UserQuery(
this.reference,
this._collection,
);
final CollectionReference<Object?> _collection;
final Query<User> reference;
get _$UserFieldMap => null;
UserQuerySnapshot _decodeSnapshot(
QuerySnapshot<User> snapshot,
) {
final docs = snapshot.docs.map((e) {
return UserQueryDocumentSnapshot._(e, e.data());
}).toList();
final docChanges = snapshot.docChanges.map((change) {
return FirestoreDocumentChange<UserDocumentSnapshot>(
type: change.type,
oldIndex: change.oldIndex,
newIndex: change.newIndex,
doc: UserDocumentSnapshot._(change.doc, change.doc.data()),
);
}).toList();
return UserQuerySnapshot._(
snapshot,
docs,
docChanges,
);
}
Stream<UserQuerySnapshot> snapshots([SnapshotOptions? options]) {
return reference.snapshots().map(_decodeSnapshot);
}
Future<UserQuerySnapshot> get([GetOptions? options]) {
return reference.get(options).then(_decodeSnapshot);
}
UserQuery limit(int limit) {
return _$UserQuery(
reference.limit(limit),
_collection,
);
}
UserQuery limitToLast(int limit) {
return _$UserQuery(
reference.limitToLast(limit),
_collection,
);
}
UserQuery orderByFieldPath(
FieldPath fieldPath, {
bool descending = false,
Object? startAt = _sentinel,
Object? startAfter = _sentinel,
Object? endAt = _sentinel,
Object? endBefore = _sentinel,
UserDocumentSnapshot? startAtDocument,
UserDocumentSnapshot? endAtDocument,
UserDocumentSnapshot? endBeforeDocument,
UserDocumentSnapshot? startAfterDocument,
}) {
var query = reference.orderBy(fieldPath, descending: descending);
if (startAtDocument != null) {
query = query.startAtDocument(startAtDocument.snapshot);
}
if (startAfterDocument != null) {
query = query.startAfterDocument(startAfterDocument.snapshot);
}
if (endAtDocument != null) {
query = query.endAtDocument(endAtDocument.snapshot);
}
if (endBeforeDocument != null) {
query = query.endBeforeDocument(endBeforeDocument.snapshot);
}
if (startAt != _sentinel) {
query = query.startAt([startAt]);
}
if (startAfter != _sentinel) {
query = query.startAfter([startAfter]);
}
if (endAt != _sentinel) {
query = query.endAt([endAt]);
}
if (endBefore != _sentinel) {
query = query.endBefore([endBefore]);
}
return _$UserQuery(query, _collection);
}
UserQuery whereFieldPath(
FieldPath fieldPath, {
Object? isEqualTo,
Object? isNotEqualTo,
Object? isLessThan,
Object? isLessThanOrEqualTo,
Object? isGreaterThan,
Object? isGreaterThanOrEqualTo,
Object? arrayContains,
List<Object?>? arrayContainsAny,
List<Object?>? whereIn,
List<Object?>? whereNotIn,
bool? isNull,
}) {
return _$UserQuery(
reference.where(
fieldPath,
isEqualTo: isEqualTo,
isNotEqualTo: isNotEqualTo,
isLessThan: isLessThan,
isLessThanOrEqualTo: isLessThanOrEqualTo,
isGreaterThan: isGreaterThan,
isGreaterThanOrEqualTo: isGreaterThanOrEqualTo,
arrayContains: arrayContains,
arrayContainsAny: arrayContainsAny,
whereIn: whereIn,
whereNotIn: whereNotIn,
isNull: isNull,
),
_collection,
);
}
UserQuery whereDocumentId({
String? isEqualTo,
String? isNotEqualTo,
String? isLessThan,
String? isLessThanOrEqualTo,
String? isGreaterThan,
String? isGreaterThanOrEqualTo,
bool? isNull,
List<String>? whereIn,
List<String>? whereNotIn,
}) {
return _$UserQuery(
reference.where(
FieldPath.documentId,
isEqualTo: isEqualTo,
isNotEqualTo: isNotEqualTo,
isLessThan: isLessThan,
isLessThanOrEqualTo: isLessThanOrEqualTo,
isGreaterThan: isGreaterThan,
isGreaterThanOrEqualTo: isGreaterThanOrEqualTo,
isNull: isNull,
whereIn: whereIn,
whereNotIn: whereNotIn,
),
_collection,
);
}
UserQuery whereName({
String? isEqualTo,
String? isNotEqualTo,
String? isLessThan,
String? isLessThanOrEqualTo,
String? isGreaterThan,
String? isGreaterThanOrEqualTo,
bool? isNull,
List<String>? whereIn,
List<String>? whereNotIn,
}) {
return _$UserQuery(
reference.where(
_$UserFieldMap["name"]!,
isEqualTo: isEqualTo,
isNotEqualTo: isNotEqualTo,
isLessThan: isLessThan,
isLessThanOrEqualTo: isLessThanOrEqualTo,
isGreaterThan: isGreaterThan,
isGreaterThanOrEqualTo: isGreaterThanOrEqualTo,
isNull: isNull,
whereIn: whereIn,
whereNotIn: whereNotIn,
),
_collection,
);
}
UserQuery whereAge({
int? isEqualTo,
int? isNotEqualTo,
int? isLessThan,
int? isLessThanOrEqualTo,
int? isGreaterThan,
int? isGreaterThanOrEqualTo,
bool? isNull,
List<int>? whereIn,
List<int>? whereNotIn,
}) {
return _$UserQuery(
reference.where(
_$UserFieldMap["age"]!,
isEqualTo: isEqualTo,
isNotEqualTo: isNotEqualTo,
isLessThan: isLessThan,
isLessThanOrEqualTo: isLessThanOrEqualTo,
isGreaterThan: isGreaterThan,
isGreaterThanOrEqualTo: isGreaterThanOrEqualTo,
isNull: isNull,
whereIn: whereIn,
whereNotIn: whereNotIn,
),
_collection,
);
}
UserQuery whereEmail({
String? isEqualTo,
String? isNotEqualTo,
String? isLessThan,
String? isLessThanOrEqualTo,
String? isGreaterThan,
String? isGreaterThanOrEqualTo,
bool? isNull,
List<String>? whereIn,
List<String>? whereNotIn,
}) {
return _$UserQuery(
reference.where(
_$UserFieldMap["email"]!,
isEqualTo: isEqualTo,
isNotEqualTo: isNotEqualTo,
isLessThan: isLessThan,
isLessThanOrEqualTo: isLessThanOrEqualTo,
isGreaterThan: isGreaterThan,
isGreaterThanOrEqualTo: isGreaterThanOrEqualTo,
isNull: isNull,
whereIn: whereIn,
whereNotIn: whereNotIn,
),
_collection,
);
}
UserQuery whereCreatedAt({
Timestamp? isEqualTo,
Timestamp? isNotEqualTo,
Timestamp? isLessThan,
Timestamp? isLessThanOrEqualTo,
Timestamp? isGreaterThan,
Timestamp? isGreaterThanOrEqualTo,
bool? isNull,
List<Timestamp?>? whereIn,
List<Timestamp?>? whereNotIn,
}) {
return _$UserQuery(
reference.where(
_$UserFieldMap["createdAt"]!,
isEqualTo: isEqualTo,
isNotEqualTo: isNotEqualTo,
isLessThan: isLessThan,
isLessThanOrEqualTo: isLessThanOrEqualTo,
isGreaterThan: isGreaterThan,
isGreaterThanOrEqualTo: isGreaterThanOrEqualTo,
isNull: isNull,
whereIn: whereIn,
whereNotIn: whereNotIn,
),
_collection,
);
}
UserQuery orderByDocumentId({
bool descending = false,
Object? startAt = _sentinel,
Object? startAfter = _sentinel,
Object? endAt = _sentinel,
Object? endBefore = _sentinel,
UserDocumentSnapshot? startAtDocument,
UserDocumentSnapshot? endAtDocument,
UserDocumentSnapshot? endBeforeDocument,
UserDocumentSnapshot? startAfterDocument,
}) {
var query = reference.orderBy(FieldPath.documentId, descending: descending);
if (startAtDocument != null) {
query = query.startAtDocument(startAtDocument.snapshot);
}
if (startAfterDocument != null) {
query = query.startAfterDocument(startAfterDocument.snapshot);
}
if (endAtDocument != null) {
query = query.endAtDocument(endAtDocument.snapshot);
}
if (endBeforeDocument != null) {
query = query.endBeforeDocument(endBeforeDocument.snapshot);
}
if (startAt != _sentinel) {
query = query.startAt([startAt]);
}
if (startAfter != _sentinel) {
query = query.startAfter([startAfter]);
}
if (endAt != _sentinel) {
query = query.endAt([endAt]);
}
if (endBefore != _sentinel) {
query = query.endBefore([endBefore]);
}
return _$UserQuery(query, _collection);
}
UserQuery orderByName({
bool descending = false,
Object? startAt = _sentinel,
Object? startAfter = _sentinel,
Object? endAt = _sentinel,
Object? endBefore = _sentinel,
UserDocumentSnapshot? startAtDocument,
UserDocumentSnapshot? endAtDocument,
UserDocumentSnapshot? endBeforeDocument,
UserDocumentSnapshot? startAfterDocument,
}) {
var query =
reference.orderBy(_$UserFieldMap["name"]!, descending: descending);
if (startAtDocument != null) {
query = query.startAtDocument(startAtDocument.snapshot);
}
if (startAfterDocument != null) {
query = query.startAfterDocument(startAfterDocument.snapshot);
}
if (endAtDocument != null) {
query = query.endAtDocument(endAtDocument.snapshot);
}
if (endBeforeDocument != null) {
query = query.endBeforeDocument(endBeforeDocument.snapshot);
}
if (startAt != _sentinel) {
query = query.startAt([startAt]);
}
if (startAfter != _sentinel) {
query = query.startAfter([startAfter]);
}
if (endAt != _sentinel) {
query = query.endAt([endAt]);
}
if (endBefore != _sentinel) {
query = query.endBefore([endBefore]);
}
return _$UserQuery(query, _collection);
}
UserQuery orderByAge({
bool descending = false,
Object? startAt = _sentinel,
Object? startAfter = _sentinel,
Object? endAt = _sentinel,
Object? endBefore = _sentinel,
UserDocumentSnapshot? startAtDocument,
UserDocumentSnapshot? endAtDocument,
UserDocumentSnapshot? endBeforeDocument,
UserDocumentSnapshot? startAfterDocument,
}) {
var query =
reference.orderBy(_$UserFieldMap["age"]!, descending: descending);
if (startAtDocument != null) {
query = query.startAtDocument(startAtDocument.snapshot);
}
if (startAfterDocument != null) {
query = query.startAfterDocument(startAfterDocument.snapshot);
}
if (endAtDocument != null) {
query = query.endAtDocument(endAtDocument.snapshot);
}
if (endBeforeDocument != null) {
query = query.endBeforeDocument(endBeforeDocument.snapshot);
}
if (startAt != _sentinel) {
query = query.startAt([startAt]);
}
if (startAfter != _sentinel) {
query = query.startAfter([startAfter]);
}
if (endAt != _sentinel) {
query = query.endAt([endAt]);
}
if (endBefore != _sentinel) {
query = query.endBefore([endBefore]);
}
return _$UserQuery(query, _collection);
}
UserQuery orderByEmail({
bool descending = false,
Object? startAt = _sentinel,
Object? startAfter = _sentinel,
Object? endAt = _sentinel,
Object? endBefore = _sentinel,
UserDocumentSnapshot? startAtDocument,
UserDocumentSnapshot? endAtDocument,
UserDocumentSnapshot? endBeforeDocument,
UserDocumentSnapshot? startAfterDocument,
}) {
var query =
reference.orderBy(_$UserFieldMap["email"]!, descending: descending);
if (startAtDocument != null) {
query = query.startAtDocument(startAtDocument.snapshot);
}
if (startAfterDocument != null) {
query = query.startAfterDocument(startAfterDocument.snapshot);
}
if (endAtDocument != null) {
query = query.endAtDocument(endAtDocument.snapshot);
}
if (endBeforeDocument != null) {
query = query.endBeforeDocument(endBeforeDocument.snapshot);
}
if (startAt != _sentinel) {
query = query.startAt([startAt]);
}
if (startAfter != _sentinel) {
query = query.startAfter([startAfter]);
}
if (endAt != _sentinel) {
query = query.endAt([endAt]);
}
if (endBefore != _sentinel) {
query = query.endBefore([endBefore]);
}
return _$UserQuery(query, _collection);
}
UserQuery orderByCreatedAt({
bool descending = false,
Object? startAt = _sentinel,
Object? startAfter = _sentinel,
Object? endAt = _sentinel,
Object? endBefore = _sentinel,
UserDocumentSnapshot? startAtDocument,
UserDocumentSnapshot? endAtDocument,
UserDocumentSnapshot? endBeforeDocument,
UserDocumentSnapshot? startAfterDocument,
}) {
var query =
reference.orderBy(_$UserFieldMap["createdAt"]!, descending: descending);
if (startAtDocument != null) {
query = query.startAtDocument(startAtDocument.snapshot);
}
if (startAfterDocument != null) {
query = query.startAfterDocument(startAfterDocument.snapshot);
}
if (endAtDocument != null) {
query = query.endAtDocument(endAtDocument.snapshot);
}
if (endBeforeDocument != null) {
query = query.endBeforeDocument(endBeforeDocument.snapshot);
}
if (startAt != _sentinel) {
query = query.startAt([startAt]);
}
if (startAfter != _sentinel) {
query = query.startAfter([startAfter]);
}
if (endAt != _sentinel) {
query = query.endAt([endAt]);
}
if (endBefore != _sentinel) {
query = query.endBefore([endBefore]);
}
return _$UserQuery(query, _collection);
}
bool operator ==(Object other) {
return other is _$UserQuery &&
other.runtimeType == runtimeType &&
other.reference == reference;
}
int get hashCode => Object.hash(runtimeType, reference);
}
class UserQuerySnapshot
extends FirestoreQuerySnapshot<User, UserQueryDocumentSnapshot> {
UserQuerySnapshot._(
this.snapshot,
this.docs,
this.docChanges,
);
final QuerySnapshot<User> snapshot;
final List<UserQueryDocumentSnapshot> docs;
final List<FirestoreDocumentChange<UserDocumentSnapshot>> docChanges;
}
class UserQueryDocumentSnapshot extends FirestoreQueryDocumentSnapshot<User>
implements UserDocumentSnapshot {
UserQueryDocumentSnapshot._(this.snapshot, this.data);
final QueryDocumentSnapshot<User> snapshot;
UserDocumentReference get reference {
return UserDocumentReference(snapshot.reference);
}
final User data;
}
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
User _$UserFromJson(Map<String, dynamic> json) => User(
name: json['name'] as String,
age: json['age'] as int,
email: json['email'] as String,
createdAt: _$JsonConverterFromJson<Timestamp, Timestamp>(
json['createdAt'], const FirestoreTimestampConverter().fromJson),
);
Map<String, dynamic> _$UserToJson(User instance) => <String, dynamic>{
'name': instance.name,
'age': instance.age,
'email': instance.email,
'createdAt': _$JsonConverterToJson<Timestamp, Timestamp>(
instance.createdAt, const FirestoreTimestampConverter().toJson),
};
Value? _$JsonConverterFromJson<Json, Value>(
Object? json,
Value? Function(Json json) fromJson,
) =>
json == null ? null : fromJson(json as Json);
Json? _$JsonConverterToJson<Json, Value>(
Value? value,
Json? Function(Value value) toJson,
) =>
value == null ? null : toJson(value);
エディタやIDEの機能を使ってgetterを追加しないとエラーが消えないので、追加します。
これでいいのか疑問😅
アプリ側のプログラムはこのようになっております
main.dart
import 'package:cloud_firestore_odm/cloud_firestore_odm.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:odm_app/firebase_options.dart';
import 'package:odm_app/user.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: UsersList(),
);
}
}
class UsersList extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Cloud FireStore ODM'),
),
body: Center(
child: FirestoreBuilder<UserQuerySnapshot>(
ref: usersRef,
builder: (context, AsyncSnapshot<UserQuerySnapshot> snapshot,
Widget? child) {
if (snapshot.hasError) return Text('Something went wrong!');
if (!snapshot.hasData) return Text('Loading users...');
// Access the QuerySnapshot
UserQuerySnapshot querySnapshot = snapshot.requireData;
return ListView.builder(
itemCount: querySnapshot.docs.length,
itemBuilder: (context, index) {
// Access the User instance
User user = querySnapshot.docs[index].data;
// createdAtの後に?.toDate()をつけてDateTimeへ変換する
// DateTimeへ変換するに変換しないと、人間の目には見ずらい時間が表示される!
return Text('User name: ${user.email}, age ${user.createdAt?.toDate()}');
},
);
}),
),
);
}
}
Flutter WebでビルドするとFireStroeの値を取得できているのを確認できました。
こちらは修正前の画面。時間が見ずらい!
こちらが修正後の画面。見やすくなりました。
表示する情報を増やしたいので、TextWidgetをWrapして、レイアウト変更してみます。最初これやってた時に何故か途中で表示できなくなった?
私物のintelのMacでは問題ない?、やり方が良くなかった🤔
データも追加してみた。最初使って見た時何故かwarningなんとかってエラーが、画面に表示される?
今はない。なぜだ....
main.dart
import 'package:cloud_firestore_odm/cloud_firestore_odm.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:odm_app/firebase_options.dart';
import 'package:odm_app/user.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: UsersList(),
);
}
}
class UsersList extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Cloud FireStore ODM'),
),
body: Center(
child: FirestoreBuilder<UserQuerySnapshot>(
ref: usersRef,
builder: (context, AsyncSnapshot<UserQuerySnapshot> snapshot,
Widget? child) {
if (snapshot.hasError) return Text('Something went wrong!');
if (!snapshot.hasData) return Text('Loading users...');
// Access the QuerySnapshot
UserQuerySnapshot querySnapshot = snapshot.requireData;
return ListView.builder(
itemCount: querySnapshot.docs.length,
itemBuilder: (context, index) {
// Access the User instance
User user = querySnapshot.docs[index].data;
// createdAtの後に?.toDate()をつけてDateTimeへ変換する
// DateTimeへ変換するに変換しないと、人間の目には見ずらい時間が表示される!
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(height: 40),
Text('User name: ${user.name}, age ${user.age}'),
Text('User name: ${user.email}, age ${user.createdAt?.toDate()}'),
SizedBox(height: 20),
],
);
},
);
}),
),
);
}
}
iOSでbuildする。見た目が崩れるので、文字を減らして日本語の表示に変えました。
使って見た感想
Freezedと違ってTimestmpConverterなるクラスを作らなくてもよくて、@の後に決まったコードを書くといい感じでやってくれるみたいです。以前はTimestmp型への対応がされていなかったそうです。
まだ、試作品らしく不具合が多いかもしれないですね🤔
でも、人気があるみたいでこれから流行っていくのだろうと思います。私も積極的に使っていきたいですね。
toMapとかtoJSONと毎回かくの大変でして、できれば自動化したいです😇
Discussion