Closed mohammadameer closed 4 years ago
You need to explain it better for me to understand what's the problem you're having, exactly. Could you be more specific, and give me more details? What are you trying to do, and what is not working?
if you see this code
AppPersistor persistor = AppPersistor();
var state = await persistor.readState(); // get old state
if (state == null) { // if there is no old state
state = AppState.initialState(); // initialize the state
await persistor.saveInitialState(state); // save the initialized state
}
Store<AppState> store = Store<AppState>(
initialState: state,
persistor: persistor,
modelObserver: DefaultModelObserver());
we are getting the old state if there is no state we will initialize the state and save it
the problem is when we add a new property to the state it value not be initialized because there is old state and it's value will be null
So, you evolved your state that now has new information, and you want to do a "database migration" from the old state schema to the new one.
Basically you have to detect you don't have the old state, and then create it.
You have two options:
1) Detect that some state that should not be null was read as null, and then instantiate it directly:
var state = await persistor.readState(); // get old state
if (state == null) { // if there is no old state
state = AppState.initialState(); // initialize the state
await persistor.saveInitialState(state); // save the initialized state
}
else {
if (state.myNewInfo == null) state = state.copy(myNewInfo: MyNewInfo.initialState());
await persistor.saveInitialState(state); // save the initialized state
}
2) Save a version number in the state, and upgrade it explicitly as needed:
static const version = "1.2";
var state = await persistor.readState(); // get old state
if (state == null) { // if there is no old state
state = AppState.initialState(); // initialize the state
await persistor.saveInitialState(state); // save the initialized state
}
else {
if (state.version != version) state = state.copy(version: version, myNewInfo: MyNewInfo.initialState());
await persistor.saveInitialState(state); // save the initialized state
}
I have found that we can use @JsonKey(defaultValue: ...)
to give the field value if it was null when serialization fromJson but when I want to give a subState a default value I get this error
this is my UserState.dart
import 'package:json_annotation/json_annotation.dart';
import 'package:saree3/models/Notification.dart';
import 'package:saree3/store/DelivererState.dart';
part 'UserState.g.dart';
@JsonSerializable(explicitToJson: true, nullable: true)
class UserState {
final String id;
final String token;
final String registrationToken;
final String fullName;
final String phone;
final String code;
final num walletBalance;
final String walletId;
final bool isDeliverer;
final String vehicleType;
final String vehicleProof;
final String cardID;
final String imageID;
final String location;
final DelivererState delivererState;
final bool newNotification;
final List<Notification> notifications;
UserState(
{this.id,
this.token,
this.registrationToken,
this.fullName,
this.phone,
this.code,
this.walletBalance,
this.walletId,
this.isDeliverer,
this.vehicleType,
this.vehicleProof,
this.cardID,
this.imageID,
this.location,
this.delivererState,
this.newNotification,
this.notifications});
UserState copy(
{String id,
String token,
String registrationToken,
String fullName,
String phone,
String code,
num walletBalance,
String walletId,
bool isDeliverer,
String vehicleType,
String vehicleProof,
String cardID,
String imageID,
String location,
DelivererState delivererState,
bool newNotification,
List<Notification> notifications}) =>
UserState(
id: id ?? this.id,
token: token ?? this.token,
registrationToken: registrationToken ?? this.registrationToken,
fullName: fullName ?? this.fullName,
phone: phone ?? this.phone,
code: code ?? this.code,
walletBalance: walletBalance ?? this.walletBalance,
walletId: walletId ?? this.walletId,
isDeliverer: isDeliverer ?? this.isDeliverer,
vehicleType: vehicleType ?? this.vehicleType,
vehicleProof: vehicleProof ?? this.vehicleProof,
cardID: cardID ?? this.cardID,
imageID: imageID ?? this.imageID,
location: location ?? this.location,
delivererState: delivererState ?? this.delivererState,
newNotification: newNotification ?? this.newNotification,
notifications: notifications ?? this.notifications);
static UserState initialState() => UserState(
id: "",
token: "",
registrationToken: "",
fullName: "",
phone: "",
code: "",
isDeliverer: false,
vehicleType: "",
vehicleProof: "",
cardID: "",
imageID: "",
location: "",
delivererState: DelivererState.initialState(),
newNotification: false,
notifications: List.unmodifiable(<Notification>[]));
factory UserState.fromJson(Map<String, dynamic> json) =>
_$UserStateFromJson(json);
Map<String, dynamic> toJson() => _$UserStateToJson(this);
@override
bool operator ==(other) =>
identical(this, other) ||
other is UserState &&
runtimeType == other.runtimeType &&
id == other.id &&
token == other.token &&
registrationToken == other.registrationToken &&
fullName == other.fullName &&
phone == other.phone &&
code == other.code &&
isDeliverer == other.isDeliverer &&
vehicleType == other.vehicleType &&
vehicleProof == other.vehicleProof &&
cardID == other.cardID &&
imageID == other.imageID &&
location == other.location &&
delivererState == other.delivererState;
@override
int get hashCode =>
id.hashCode ^
token.hashCode ^
hashCode ^
fullName.hashCode ^
phone.hashCode ^
code.hashCode ^
isDeliverer.hashCode ^
vehicleType.hashCode ^
vehicleProof.hashCode ^
cardID.hashCode ^
imageID.hashCode ^
location.hashCode ^
delivererState.hashCode;
}
Your error message says you can only define a default value like this if it is constant.
I guess it'll work if UserState.initialState
is a const constructor (see https://flutterigniter.com/dart-const-constructor).
Something along the lines of:
const UserState.initialState() : this(
id: "",
token: "",
registrationToken: "",
fullName: "",
phone: "",
code: "",
isDeliverer: false,
vehicleType: "",
vehicleProof: "",
cardID: "",
imageID: "",
location: "",
delivererState: null,
newNotification: false,
notifications: const <Notification>[],
);
and then:
@JsonKey(defaultValue: const UserState.initialState())
in our app, we are using shared Preferences to store the last state and use it again
the problem is that when we add new properties to the state new properties values are null because of how we handle old state how we can fix that and what is the best way
AppPersistor.dart
main.dart