flutter: json_serializable how set converter globally - flutter

How can I set a converter globally to replace the buildin datetime for example?
this does not appear in the documentation
https://pub.dev/packages/json_serializable
replace the datetime converter with a custom one globally for all classes

First, create your converter:
class DateTimestampConverter implements JsonConverter<DateTime?, Timestamp?> {
const DateTimestampConverter();
#override
DateTime? fromJson(Timestamp? timestamp) => timestamp?.toDate();
#override
Timestamp? toJson(DateTime? dateTime) => dateTime != null ? Timestamp.fromDate(dateTime) : null;
}
Then add it to your #JsonSerializable annotation:
#JsonSerializable(
explicitToJson: true,
converters: [DateTimestampConverter()],
)

Related

How can I retrieve data by year like pic using flutter and hive db?

How can I retrieve data by year like pic using flutter and hive db?
My class is like this:
#HiveType(typeId: 1)
class Pulse extends HiveObject {
#HiveField(0)
DateTime dateTime;
#HiveField(2)
int pulseRate;
#HiveField(3)
int saturation;
#HiveField(4)
bool isOpen;
Pulse({
required this.dateTime,
required this.pulseRate,
required this.saturation,
this.isOpen = false,
});
}
since there is no box example, I will say that if we have a box likt this:
Hive.box<Pulse>('pulseBox));
then you can get Pulse object values which have a specific year in their DateTime with the where like this:
Hive.box<Pulse>('pulseBox)).values.where((pulseElement) => pulseElement.dateTime.year == 2022);
This will return a List<Pulse> of all elements inside the box which have a DateTime with the 2022 year.

How to make optional datetime parameter in Flutter with null safety

I'm new to Flutter development and trying to learn.
I want to create a model with a constructor, one of which contains a field of type DateTime which is optional.
I tried by making it like this:
import 'package:equatable/equatable.dart';
class Customer extends Equatable {
final int indexs;
final DateTime apply_date;
Customer({
required this.indexs,
this.apply_date,
});
#override
List<Object?> get props => throw UnimplementedError();
}
But an error message appears like this
The parameter 'apply_date' can't have a value of 'null' because of its
type, but the implicit default value is 'null'. Try adding either an
explicit non-'null' default value or the 'required' modifier.
I've tried to learn from this and this reference, and what I understand there are 3 ways:
Include required modifiers
Set initial value
Nulllabel parameter / Fill it with (?) => I don't understand this
So how to do this properly?
I don't want to make this field required, because it's optional.
I also don't know what to fill if I want to fill it with an initialvalue.
Thank you!
Making the attribute nullable is the same as making it an optional attribute.
You can do that by adding ? behind the attribute's type.
class Customer extends Equatable {
final int indexs;
final DateTime? apply_date;
Customer({
required this.indexs,
this.apply_date,
});
#override
List<Object?> get props => throw UnimplementedError();
}

How to create Hive adapter for XFile class

I'm trying to store custom object that has variable storing list of XFile's; cross platform image representation from package called image_picker version 0.8.4+3. When writing an error occurs saying that im missing Adapter for XFile which is understandable, but I'm having hard time deciding how to declare such Adapter for external source file class.
This is my Receipt class that has some list of XFile's.
Note: I've removed nonmeaningful variables from snippet.
#HiveType(typeId: 0)
class Receipt extends HiveObject with EquatableMixin {
Receipt({
List<XFile>? files,
}) {
this.files = files ?? <XFile>[];
}
#HiveField(6)
late final List<XFile> files;
#override
List<Object?> get props => [
files,
];
}
Now I was thinking about two possible solutions; one - copy whole source code from XFile, add HiveType and HiveField decorators and generate adapter from that or two - create class that will extend from XFile and add decorators something like this:
#HiveType(typeId: 1)
class XFileAdapter extends XFile with HiveObjectMixin {
// access fields and add decorators here
}
but I have no clue how to add decorators to these field without overriding every one of them. And even if I knew how to do that, it turns out that XFile's doesn't have its own variables I've could add Hive decorators to, it simply takes paramethers and passes them down to XFileBase class since it further decides what to do with them.
Very similar question has been asked in this thread but the only aswer suggests creating new class from scratch that imitates source class which is not solution to my problem.
I think creating a new MyXFile class as you suggested might be the way to go. But as you've said you will need to override the properties you want to keep in hive. This code seems to be working as intended:
Code
import 'dart:typed_data';
import 'package:image_picker/image_picker.dart';
import 'package:hive_flutter/adapters.dart';
part 'my_xfile.g.dart';
#HiveType(typeId: 1)
class MyXFile extends XFile {
#override
#HiveField(1)
final String path;
#override
#HiveField(2)
final String? mimeType;
#HiveField(3)
final String? _name;
/// The base implementation of `XFileBase.name` throws an
/// [UnimplementedError] so we are overriding it to return a known
/// [_name] value.
#override
String get name {
if (_name != null) {
return _name!;
}
return super.name;
}
#HiveField(4)
final int? _length;
/// The base implementation of `XFileBase.length()` throws an
/// [UnimplementedError] so we are overriding it to return a known
/// [_length] value.
#override
Future<int> length() {
return _length != null ? Future.value(_length!) : super.length();
}
#HiveField(5)
final Uint8List? bytes;
#HiveField(6)
final DateTime? _lastModified;
/// The base implementation of `XFileBase.lastModified()` throws an
/// [UnimplementedError] so we are overriding it to return a known
/// [_lastModified] value.
#override
Future<DateTime> lastModified() {
return _lastModified != null
? Future.value(_lastModified!)
: super.lastModified();
}
MyXFile(
this.path, {
this.mimeType,
String? name,
int? length,
this.bytes,
DateTime? lastModified,
}) : _name = name,
_length = length,
_lastModified = lastModified,
super(
path,
mimeType: mimeType,
name: name,
length: length,
bytes: bytes,
lastModified: lastModified,
);
}
By using this I've been able to save and retrieve my object MyXFile and as it is extending XFile you should be able to use it the same way.
Then instead of having a List<XFile>? files in your Receipt class you will need a List<MyXFile>? files.

when to implements an abstract class in freezed?

I need to understand this code, resoCoder did it on DDD Playlist. why does he implements IEntity inside freezed?
The code is:
#freezed
abstract class TodoItem with _$TodoItem implements IEntity {
const factory TodoItem({
#required UniqueId id,
#required TodoName name,
#required bool done,
}) = _TodoItem;
factory TodoItem.empty() => TodoItem(
id: UniqueId(),
name: TodoName(''),
done: false,
);
}
}
IEntity code is:
abstract class IEntity {
UniqueId get id;
}
UniqueId Code is:
class UniqueId extends ValueObject<String> {
#override
final Either<ValueFailure<String>, String> value;
// We cannot let a simple String be passed in. This would allow for possible non-unique IDs.
factory UniqueId() {
return UniqueId._(
right(Uuid().v1()),
);
}
/// Used with strings we trust are unique, such as database IDs.
factory UniqueId.fromUniqueString(String uniqueIdStr) {
assert(uniqueIdStr != null);
return UniqueId._(
right(uniqueIdStr),
);
}
const UniqueId._(this.value);
}
It ensures consistency; TodoItem must implement everything as per IEntity.
Let's imagine one day you want to add an attribute "createdAt" to IEntity: in this case, you will have to add "createdAt" to every class that implements IEntity across the project, otherwise the compiler will let you know you're missing something :D
Some code now.
The result would be
abstract class IEntity {
UniqueId get id;
int get createdAt; // let's keep it "int" for the example purpose
}
then you would have to update the freezed class too
#freezed
abstract class TodoItem with _$TodoItem implements IEntity {
const factory TodoItem({
#required UniqueId id,
#required int createdAt,
#required TodoName name,
#required bool done,
}) = _TodoItem;
factory TodoItem.empty() => TodoItem(
id: UniqueId(),
createdAt: 1234,
name: TodoName(''),
done: false,
);
}
}

DateTime objects not working with collection-if feature in Dart

I'm using the Dart feature Collection-if introduced in Dart 2.3. My model class is
class Calendar {
Calendar(
{this.headerDate, this.releaseDate, this.period,this.title});
final DateTime headerDate;
final DateTime releaseDate;
final String title;
final String period;
factory Calendar.fromMap(Map<String, dynamic> value) {
final int releaseDateMilliseconds = value['releaseDate'];
final int headerDateMilliseconds= value['headerDate'];
return Calendar(
releaseDate: DateTime.fromMillisecondsSinceEpoch(releaseDateMilliseconds),
headerDate: DateTime.fromMillisecondsSinceEpoch(headerDateMilliseconds),
title: value['title'],
period: value['period'],
);
}
}
The feature works fine when I'm dealing with Strings but doesn't work when I check for null for for the DateTime objects. The dates are stored as numbers in firestore and converted in to DateTime objects. Here is my build method:
#override
Widget build(BuildContext context) {
return Column(children: [
if(calendar.title!=null) /// Works
Text(calendar.title),
if(calendar.period!=null) ///Works
Text(calendar.period),
if(calendar.headerDate!=null) /// Doesn't work
Text(Format.date(calendar.headerDate)),
Text(Format.date(calendar.releaseDate)),
]);
}