Why does it throw an Unhandled Exception here? - flutter

I'm trying to persist my calendar data with hive but when I start the program, it throws this:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'Null' is not a subtype of type 'bool' in type cast
This is my model class:
#HiveType(typeId: 1)
class Event extends HiveObject {
#HiveField(0)
late String title;
#HiveField(1)
late DateTime eventDateTime;
#HiveField(2)
bool wholeDayEvent;
Event({
required this.title,
required this.eventDateTime,
required this.wholeDayEvent,
});
#override
String toString() => title;
}
And here's the build method of my displaying widget:
Expanded(
child: ValueListenableBuilder<Box<Event>>(
valueListenable: Boxes.getEvents().listenable(),
builder: (context, box, _) {
final events = box.values.toList().cast<Event>();
return ListView.builder(
itemCount: events.length,
itemBuilder: (context, index) {
return Container(
margin: const EdgeInsets.symmetric(
horizontal: 12.0,
vertical: 4.0,
),
decoration: BoxDecoration(
border: Border.all(),
borderRadius: BorderRadius.circular(12.0),
),
child: ListTile(
onTap: () => print('${box.values}'),
title: Text('${box.values}'),
),
);
},
);
},
),
),

I can assume that you changed some fields in your Event object, while your Hive database is not empty, so the previously stored objects do not have those new fields so their values are null, which throws the error.
You can fix this by simply clearing your Hive box before using it, so it deletes the previous data objects and work with the new one, in your main():
await Hive.openBox<Event>("yourBoxName"); // opens the box
await Hive.box<Event>("yourBoxName").clear(); // clear the box
Now you will have an empty box, and your code will work fine again.
you should just clear it one time to remove previous data, after that you could remove the clear() line and work normally.

Related

The method '[]' can't be unconditionally invoked because the receiver can be 'null'. flutter firebase

I couldn't retrieve the data from another screen from an item within a list view using flutter and firebase. I keep having this error even if add a call condition using ? or when i add a null check when i add !.
I am trying to add a comment on an item from a list view in another screen and to do that i tried to retrieve the title of the item. Then when the user adds a comment, the comment will be added in the firestore with in a document that has the title of the item and the comment.
The problem is that i get that error in this line:
then((value) => value.data()["titre"])
I tried adding ! or ?, but it just didn't work the problem keeps occurring. There were people who said that I should transform me to then((value) =\> value.data\["titre"\]), but with no clue can someone help me solve it ?
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
class add_comment extends StatefulWidget {
final DocumentReference docRef;
const add_comment({key, required this.docRef, required titre})
: super(key: key);
#override
State<add_comment> createState() => _add_commentState();
}
class _add_commentState extends State<add_comment> {
TextEditingController commentController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
padding: EdgeInsets.all(5),
child: Row(
children: [
Expanded(
child: TextFormField(
controller: commentController,
minLines: 1,
maxLength: 5,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15))),
)),
SizedBox(
width: 5,
),
CircleAvatar(
radius: 25,
backgroundColor: Colors.green,
child: IconButton(
icon: Icon(Icons.send, color: Colors.white),
onPressed: () async {
final Map<String, dynamic> commentData = {
'title': widget.docRef
.get()
.then((value) => value.data()["titre"]),
'text': commentController.text,
};
await FirebaseFirestore.instance
.collection('comments')
.doc(widget.docRef.id)
.collection('comments')
.add(commentData);
// Clear the comment text field
commentController.clear();
// Show a message to the user
// Scaffold.of(context).showSnackBar(
// SnackBar(content: Text('Comment added')
// ),
//);
},
),
)
],
),
)
],
),
);
}
}
The error is pretty clear: since your value is a DocumentSnapshot, its value.data() property is an Object?. The ? here means that data() can return null, which your code needs to handle.
A good way to tell your code what to do when value.data() is null is to use the ? coalescing and ?? operators:
value.data()?["titre"] ?? "no data found"
So here we say that, if value.data() is null, we'll return "no data found" instead.
There are more problems in your code though. Since you're calling widget.docRef.get(), that data is loaded from the database and is an asynchronous operation that returns a Future. You're handling that Future with then, but your .then((value) => ...) code will never render the value.
I recommend first checking whether the code actually works, by printing the value from the database:
.then((value) => {
print(value.data()?["titre"] ?? "no data found");
})
Or since it is now a block of code, we can use more readable constructs than ? and ?? and get the same result with:
.then((doc) => {
if (doc != null) {
var value = doc!
print(value["titre"]);
} else {
print("no data found");
}
})

Why I am getting type model - dynamic error on dynamic T type generic?

I have three classes,
1.UiInfiniteScroller : my statefulWidget class (classic stateful widget),
InfiniteScrollerViewModel : my view model class,and its contains an object as widget and widget is like;
final UiInfiniteScrollerWidgets<T> widgets;
UiInfiniteScrollerWidgets widgets has a function like;
final Widget Function(BuildContext context, T item) widgetBuilder;
now my problem is on itemBuilder function;
return ListView.builder(
padding: widget.padding ?? EdgeInsets.zero,
physics: widget.physics ?? const BouncingScrollPhysics(),
shrinkWrap: widget.shrinkWrap ?? false,
itemBuilder: (BuildContext context, int index) {
return widget.vM.widgets.widgetBuilder(context, widget.vM.paginationService.results[index]);
},
itemCount: widget.vM.paginationService.results.length + _additionalWidgetCount,
);
if I call this function I am getting error like
type '(BuildContext, XxModel) => SizedBox' is not a subtype of type '(BuildContext, dynamic) => Widget',
and xx Model is my T model.
if add this code
print("isType equal to T:" + (widget.vM.paginationService.results[index] is T).toString());, it is returning true, so my list is T type.
And My widget builder function is;
widgetBuilder: (BuildContext context, MockResultModel item) {
return SizedBox(
height: 35.h,
width: double.infinity,
child: Padding(
padding: const EdgeInsets.only(left: 30.0),
child: UiLexend(
text: "Item Id:${item.id} Searched Keyword: ${item.keyword}",
),
),
);
}
if I change the below line,
final Widget Function(BuildContext context, T item) widgetBuilder;
with;
final Widget Function(BuildContext context, dynamic item) widgetBuilder;
it is working correctly but if item type is T it is failing.
So why it is happening, I mean I am giving all classes the same Model type and is T are returning true but for builder function, it is giving the error :/
can anyone help me?

Expected a value of type 'String', but got one of type 'List<dynamic>' for my DropdownMenu

Got an API call that returns a bunch of data for my app. This particular data set is a Map<String, List<dynamic>>, I'm processing this data to make it usable within my app and passing it around to necessary widgets. I came across his error which makes no sense to me but it is self-explanatory looking at the code I cant see anything.
This code is a part of a bigger code please comment if you want me to add it as it just takes in a few arguments to process the Future and create the Map<String, List<dynamic>>.
This is the code where the error is being thrown (Line:45)
#override
Widget build(BuildContext context) {
return FutureBuilder<Map<String, List<dynamic>>>(
future: options,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: snapshot.data!.values.length,
itemBuilder: ((context, index) {
return DropdownMenu(items: snapshot.data!.values.toList()); //Line: 45
}),
);
} else if (snapshot.hasError) {
return Text(snapshot.error.toString());
} else {
return const CircularProgressIndicator();
}
},
);
}
This is my DropdownMenu Class
class DropdownMenu extends StatefulWidget {
DropdownMenu({super.key, required this.items});
List<dynamic> items;
#override
State<DropdownMenu> createState() => _DropdownMenuState(items);
}
class _DropdownMenuState extends State<DropdownMenu> {
_DropdownMenuState(this.items);
String? value;
List<dynamic> items;
#override
void initState() {
super.initState();
widget.items = items;
}
#override
Widget build(BuildContext context) {
return Container(
width: 300,
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.black, width: 2)),
child: DropdownButtonHideUnderline(
child: DropdownButton<dynamic>(
value: value,
onChanged: (value) => setState(() => this.value = value),
items: items.map(buildMenuItem).toList(),
),
),
);
}
DropdownMenuItem<dynamic> buildMenuItem(dynamic item) => DropdownMenuItem(
value: item,
child: Text(
item,
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
),
);
}
Error
The following TypeErrorImpl was thrown building DropdownMenu(dirty, state:
_DropdownMenuState#69c5b):
Expected a value of type 'String', but got one of type 'List<dynamic>'
The relevant error-causing widget was:
DropdownMenu
DropdownMenu:file:///C:/Main%20Storage/_GitHub%20Repos/flutter_fontend_client/lib/components/options__dropdown_menu.dart:45:22
After some debugging... I added this piece of code
var result1 = {
for (var value in snapshot.data!.values.toList())
value.first: value
};
print("Values of the snapshot: $result1");
The result is a big awkward and IDK why it like this. It prints out a json style format string {'key': ['keyStrings', 'keyStrings']
Got a different answer from someone in NorDev Discord.
I will show the answer here + keep the accepted answer as both work and I think that people will appreciate that there is multiple ways of solving this.
return DropdownMenu(items: snapshot.data!.values.elementAt(index));
According to your code, your response is a Map with strings as keys and List as values. That means that snapshot.data!.values.toList() is a list with (possibly) multiple List<dynamic> that you are passing to DropdownMenu.
DropdownMenu expects that the elements of the list are of type String but they are not.
I suspect what you want to do is actually get the first list, so you could do
return DropdownMenu(items: snapshot.data!.values.first);

Flutter: Can't solved - type 'List<dynamic>' is not a subtype of type 'List<Files>'

I have a model
class Files {
String fileName;
bool type;
Files(this.fileName, this.type);
#override
String toString() {
return '{ ${this.fileName}, ${this.type} }';
}
}
Next I define The list paths = [];
Then I run this line to add the file name and boolean type to it to find out whether the file is a directory or not
for (final file in files) {
print(file.path);
paths.add(Files(file.name.toString(), file.isDirectory));
}
return paths.toList();
I get the following data:
And when I start building a ListView with this code:
Widget listViewWidget(List<Files> file) {
return Container(
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: file.length,
itemBuilder: (context, position) {
return Card(
elevation: 8.0,
margin: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: Container(
decoration: BoxDecoration(color: Color.fromRGBO(133, 123, 122, .9)),
child: ListTile(
onTap: () {},
contentPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
title: Text(
file[position].type ? file[position].fileName+" This is a Folder" : file[position].fileName+" This is a file",
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
),
),
);
}
),
);
}
I get the following error:
type 'List<dynamic>' is not a subtype of type 'List<Files>'
Can anyone suggest what the problem might be?
On a List, you can't insert 2 values. You can only insert a File object.
Furthermore, you can't assume the type of a dynamic list to be of a class. dynamic should be of the "basic" types, like int, String, double or bool, because it might be dangerous to assume whole objects types.
What I suggest is:
List<File> paths = List<File>();
This way, you can do this:
paths.add(fileObject);
And remember, the fileObject has to be an object of the File class.
If you annotate the type for your function's parameter as List<Files>, you have to pass it exactly that. You don't show your call of listViewWidget() so I'm not sure where, but you're missing a type annotation.
If you're doing listViewWidget(paths), then declaring var paths = <Files>[]; should do the trick.

The argument type 'Color' can't be assigned to the parameter type 'int'

i'm new to flutter with dart programming.
i found an error regarding my question, that is about "i created a model class and a list, model class has a member of type Color, then in the main.dart, i want to display a list of my model data in a ListView.builder, but when in a separate widget of container, everything else works well but color property is giving error, i tried to change the type of index parameter but error stays. "
here is code:
import 'package:flutter/material.dart';
class ProductModel {
ProductModel(
this.title,
this.name,
this.image,
this.color
);
final String title;
final String name;
final String image;
final Color color;
}
final modelProduct = <ProductModel>[
ProductModel(
"titile1",
"name1",
"https://image.freepik.com/free-vector/multitasking-concept-illustration-character_23-2148403716.jpg",
Colors.pink.withOpacity(0.4),
),
ProductModel(
"titile2",
"name2",
"https://image.freepik.com/free-vector/people-putting-puzzle-pieces-together_52683-28610.jpg",
Colors.blue.withOpacity(0.4),
),
ProductModel(
"titile3",
"name3",
"https://image.freepik.com/free-vector/people-using-online-apps-set_74855-4457.jpg",
Colors.yellow.withOpacity(0.4),
),
]
and the main.dart
i skipped the boiler plate code of first flutter, and just copied that has the main thing of my concern,
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
child: ListView.builder(
itemCount: modelProduct.length,
itemBuilder: (context, index) {
return createItem(context, index);
})),
);
}
}
Widget createItem(BuildContext context, index) {
return Container(
height: MediaQuery.of(context).size.height * 0.3,
width: MediaQuery.of(context).size.width,
child: Text(modelProduct[index].title),
color: Color(modelProduct[index].color),
);
}
the issue is on color: Color(modelProduct[index].color) this line
, and the error is
The argument type 'Color' can't be assigned to the parameter type 'int'.
but i know that if i turn the type of color into int in my model class, and provide the int type value of color like 0xFFFFFF then the error is resolved, but my question is if i want to use the material color like i used above, how to do with it.
Thank you
You can directly use color: modelProduct[index].color
code snippet
return Container(
height: MediaQuery.of(context).size.height * 0.3,
width: MediaQuery.of(context).size.width,
child: Text(modelProduct[index].title),
color: modelProduct[index].color,
);
Try the below code :
Container(
height: MediaQuery.of(context).size.height* 0.3,
width: MediaQuery.of(context).size.width,
child: Text(modelProduct[index].title),
color: modelProduct[index].color
);
below works for me
return Container(
height: MediaQuery.of(context).size.height * 0.3,
width: MediaQuery.of(context).size.width,
child: Text(modelProduct[index].title),
color: modelProduct[index].color.value,
);
It takes the int value of the color