I recently made the switch to null-safety in my flutter project, which brings a new kind of problem when using the Either type (from the dartz package)
For example, before I would have some properties in my class like this:
Either<Failure, List<Product>> _products;
I would then have a function to get the products, and consume it in my view.
However, now with null safety, I need to initialize this property, because it should never be null, instead I would like to have an empty list.
If I do this
Either<Failure, List<Product?>> _products = [];
I get this error
A value of type 'List<dynamic>' can't be assigned to a variable of type 'Either<Failure, List<Product?>>'.
So my question would be, how can I initialize this property to the right value of Either, with an empty list?
Have this go:
Either<Failure, List<Product?>> _products = right([]);
you can use the new 'late' keyword that fixes this issue
late Either<Failure, List<Product?>> _products;
read more about it here
Related
I have used freezed library to manage my Remote DTO classes and Ui Models.
In this question case, my Object LifeDiagnosisResult DTO and Ui Model only have one difference - createdAt field.
When I put data, I used SharedPreference (because backend is not yet built) and put my List value by jsonEncode function.
When I get a response from SharedPreference (because backend is not yet built) , I used jsonDecode to get Map Object.
To achieve my final wish, List Object, I added createdAt field like this.
void _handleListResponseSuccess(List<String> response) {
List<LifeDiagnosisResultUiModel>? uiModelList = response.map((e) {
Map<String, dynamic> map = jsonDecode(e) as Map<String, dynamic>;
map['createdAt'] = DateTime.now();
return LifeDiagnosisResultUiModel.fromJson(map);
}).toList();
if (uiModelList.isNotEmpty) {
setLifeDiagnosisResultUiModel(uiModelList[uiModelList.length - 1]);
}
_rxList(uiModelList);
}
But, when I ran this code, type casting error was caused.
The error message is this.
error type 'DateTime' is not a subtype of type 'String' in type cast
And this is my Ui Model's createdAt field.
I think Map's createdAt could not find correct field in Ui Model.
But I have no idea why...
Could you tell me what is wrong?
I found the answer...
it is not a real answer of my question, but it can explain why this issue happen.
In dart, Map's DateTime cannot be converted to Object's DateTime.
I dont know a detail process, but in type casting, Map's DateTime is converted to String type.
I don't know if I get it right, but if you want to test your fromJson method you could do it like this:
Map<String,dynamic> response={'att1':1234,'att2':'oneTwoThree','createdAt':DateTime(2022,08,22)};
return LifeDiagnosisResultUiModel.fromJson(response);
After migrating to null safety, the migration tool added as Iterable<SetWidget> to my code. But unfortunately i get this error:
Unhandled Exception: type 'List<Widget>' is not a subtype of type 'Iterable<SetWidget>' in type cast
This is the code:
final List<Widget> _sets = [];
Map getSets() {
Map sets = {};
int k = 0;
for (SetWidget set in _sets as Iterable<SetWidget>) {
sets.putIfAbsent(k.toString(), () => set.getMap());
k++;
}
return sets;
}
What is the issue here?
I don't know why the tool decided to do that, but if you think about it, it obviously throws an error. _sets is a list of Widgets, which means it could include for example a Column, a Container, and a SetWidget, so it can't be cast to a SetWidget iterable.
is getMap() a method in the SetWidget class? if it is, could you change the List<Widget> to a List<SetWidget> and remove the as Iterable<SetWidget>? Hopefully, that solves your problem.
Also, side note, what is this code for? Are you turning a list into a Map<String, Function> where the string is just an index? if you are, why not use a list instead?
for (SetWidget widget in _sets)
{
sets.add(widget.getMap)
}
I am very new to using flutter and platform specific code so please forgive me if this is a stupid question. I am using a event channel to return data from android side to flutter. I am returning a List<List<Map<String,double>>> but when it reaches the flutter side, it becomes List dynamic. I want to add the last Map object to another list that I created on the flutter side which has the same type of List<List<Map<String,double>>>.
However, when I tried to add it, it gives an exception, "Unhandled Exception: type 'List' is not a subtype of type 'List<Map<String, double>>'".
This is the list I want to add the Map object to.
List<List<Map<String,double>>> convertedList = [];
This is my adding code. Ignore the print statement.
List<dynamic> t = event;
print( "length ${t.length}");
print("type ${t[t.length-1].runtimeType}");
convertedList.add(t[t.length - 1]);
I have tried methods like cast or from but it did not work for me as the same error came out or maybe i used it the wrong way. I really want to know how can i add the Map object to the list. Thanks so much for your help.
Try:
List<dynamic> t = event;
List<Map<String,double>> newTempList = t[t.length - 1].map((e)=>e as Map<String,double>).toList();
convertedList.add(newTempList);
//Or you can make it shorter by just using this:
List<dynamic> t = event;
convertedList.add(t[t.length - 1].map((e)=>e as Map<String,double>).toList());
Because List<List<Map<String,double>>> is technically also List<dynamic> also, but the opposite is not always true. So you have to cast your items as Map,String, double> first, add those to a list, and then add this newly generated list to your convertedList.
In the context of a Flutter 2.0.5 app whose state I'd like to manage with Riverpod, I thought I can declare a StateNotifierProvider like this:
import 'package:flutter_riverpod/flutter_riverpod.dart';
final counterProvider = StateNotifierProvider<CounterStateNotifier>((ref) => CounterStateNotifier());
class CounterStateNotifier extends StateNotifier<int> {
CounterStateNotifier([int count = 0]) : super(count);
void increment() => state++;
}
But Android Studio (and later the Dart compiler as well) complains about the line where I declare the counterProvider variable:
The type 'StateNotifierProvider' is declared with 2 type parameters, but 1 type arguments were given.
Removing the <CounterStateNotifier> type parameter in StateNotifierProvider<CounterStateNotifier> removes the error. However, attempting to read the provider and call its increment method (setting () => context.read(counterProvider).increment() as the onPressed of an ElevatedButton, then pressing the button) gives the following runtime error:
'increment'
method not found
Receiver: 0
Arguments: []
Why is context.read(counterProvider) returning the int state instead of the notifier? And what is the reason behind the type parameter error mentioned in the first part of my question?
I should mention that I'm running my app on the web (with flutter run -d Chrome).
As of Riverpod 0.14.0, State is the default value exposed by StateNotifierProvider.
The syntax for declaring your StateNotifierProvider is now as follows:
final counterProvider = StateNotifierProvider<CounterStateNotifier, int>((ref) => CounterStateNotifier());
Accessing functions now requires adding .notifier (accessing the StateNotifier itself):
context.read(counterProvider.notifier).increment();
And like you've noticed, you now access the state like so:
final count = context.read(counterProvider);
More on the changes here.
You may also use dynamic to accept any type if value for the StateNotifierProvider
final modelProvider =
StateNotifierProvider.autoDispose<ModelClassName, dynamic>(
(ref) => ModelClassName());
I need a list of my map assigned to a List variable outside of this map. How can I do that?
class Lists {
late var list = Map<int, List<int>>();
Lists() {
list[0] = [];
list[1] = [];
list[2] = [];
list[3] = [];
}
}
In another file I then try to assign the list[0] to a List variable:
List<int> listOutside = Lists.list[0];
I then receive this error:
What does the "?" mean and how can I fix that?
Thanks for the help.
Greetings
there are 2 major problems that are there.
You are trying to access a static variable outside a class which is wrong. This problem can be fixed by adding List<int> listOutside = Lists().list[0]; (notice the parentheses)
By accessing the list[0]; you are saying that the element always exists but here the compiler comes into play saying that this is a nullable list (List<int>?) which you are trying to assign to List<int> which is not possible as both have different types. This problem can be quickly fixed by using ! at the end Lists().list[0]!;
But note that this comes with a side effect that if there is no element at 0the index then this will throw NPE.
NOTE: Always avoid using ! in expressions where you are not sure that it is not nullable.
Seems to work when adding a "!".
List<int> listOutside = Lists.list[0]!;
I have no clue why, but anyways it works :D
? means that this field can have the null value. The Dart language now supports sound null safety and to indicate that a variable might have the value null, just add ? to its type declaration:
int? aNullableInt = null;
For your problem, you try to access list variable as a static usage and you use late but you initialize field immediately. For this reason, you can omit late and put static.
This usage could solve your problem:
static var list = Map<int, List<int>>();
List<int> listOutside = Lists.list[0];