════════ Exception caught by widgets library ═══════════════════════════════════ The following _CastError was thrown building Builder: type 'Null' is not a subtype of type 'String' in type cast
The relevant error-causing widget was MaterialAppenter image description here
My code is attached. It's about Maxwell Udemy Course. Shop APP module. There is an error when I press on Add button in edit_product_screen. He record the course in 2019. I am facing this error. I can't find out the error. Anyone, please Solve the error.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/product.dart';
import '../providers/products.dart';
class EditProductScreen extends StatefulWidget {
static const routeName = '/edit-product';
const EditProductScreen({super.key});
@override
State<EditProductScreen> createState() => _EditProductScreenState();
}
class _EditProductScreenState extends State<EditProductScreen> {
final priceFocus = FocusNode();
final imageControl = TextEditingController();
final form = GlobalKey<FormState>();
var isInit = true;
var initValues = {
'title': '',
'description': '',
'price': '',
'imageUrl': ''
};
var editProduct =
Product(id: '', title: '', desc: '', imageUrl: '', price: 0.0);
@override
void dispose() {
priceFocus.dispose();
imageControl.dispose();
super.dispose();
}
@override
void didChangeDependencies() {
if (isInit) {
final productid = ModalRoute.of(context)!.settings.arguments as String;
if (productid != null) {
editProduct =
Provider.of<Products>(context, listen: false).findById(productid);
initValues = {
'title': editProduct.title,
'description': editProduct.desc,
'price': editProduct.price.toString(),
'imageUrl': '',
};
imageControl.text = editProduct.imageUrl;
}
}
isInit = false;
super.didChangeDependencies();
}
void formSave() {
final valid = form.currentState!.validate();
if (!valid) {
return;
}
form.currentState!.save();
if (editProduct.id != null) {
Provider.of<Products>(context, listen: false)
.updateProduct(editProduct.id, editProduct);
} else {
Provider.of<Products>(context, listen: false).addProduct(editProduct);
}
Navigator.of(context).pop();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Edit Product'),
actions: [
IconButton(onPressed: formSave, icon: const Icon(Icons.save))
],
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: form,
child: ListView(
children: [
TextFormField(
initialValue: initValues['title'],
decoration: const InputDecoration(labelText: 'Title'),
textInputAction: TextInputAction.next,
onFieldSubmitted: (_) {
FocusScope.of(context).requestFocus(priceFocus);
},
onSaved: (newValue) {
editProduct = Product(
id: editProduct.id,
title: newValue as String,
desc: editProduct.desc,
imageUrl: editProduct.imageUrl,
price: editProduct.price,
isFavorite: editProduct.isFavorite,
);
},
validator: (value) {
if (value!.isEmpty) {
return 'Enter Title';
}
return null;
},
),
TextFormField(
initialValue: initValues['price'],
decoration: const InputDecoration(labelText: 'Price'),
textInputAction: TextInputAction.next,
keyboardType: TextInputType.number,
focusNode: priceFocus,
onSaved: (newValue) {
editProduct = Product(
id: editProduct.id,
title: editProduct.title,
desc: editProduct.desc,
imageUrl: editProduct.imageUrl,
price: double.parse(newValue as String),
isFavorite: editProduct.isFavorite,
);
},
),
TextFormField(
initialValue: initValues['description'],
decoration: const InputDecoration(labelText: 'Description'),
textInputAction: TextInputAction.next,
maxLines: 3,
keyboardType: TextInputType.multiline,
onSaved: (newValue) {
editProduct = Product(
id: editProduct.id,
title: editProduct.title,
desc: newValue as String,
imageUrl: editProduct.imageUrl,
price: editProduct.price,
isFavorite: editProduct.isFavorite,
);
},
),
Row(
children: [
Container(
height: 100,
width: 100,
margin: const EdgeInsets.only(top: 8, right: 10),
decoration: BoxDecoration(
border: Border.all(width: 1, color: Colors.grey)),
child: imageControl.text.isEmpty
? const Center(child: Text('Enter Url'))
: FittedBox(
child: Image.network(
imageControl.text,
fit: BoxFit.cover,
),
),
),
Expanded(
child: TextFormField(
decoration:
const InputDecoration(labelText: 'Image Url'),
textInputAction: TextInputAction.done,
keyboardType: TextInputType.url,
controller: imageControl,
onFieldSubmitted: (_) {
formSave();
},
onSaved: (newValue) {
editProduct = Product(
id: editProduct.id,
title: editProduct.title,
desc: editProduct.desc,
imageUrl: newValue as String,
price: editProduct.price,
isFavorite: editProduct.isFavorite,
);
},
),
),
],
),
],
)),
),
);
}
}
CodePudding user response:
Try to check in imageControl.text = editProduct.imageUrl;
editProduct.imageUrl should not be null
CodePudding user response:
In your didChangeDependencies method you are instantiating a variable called productId and you are getting a value from ModalRoute.of(context).!.settings.arguments and casting as a String, but this value can be null, that is why you check if it`s null right after that line.
@override
void didChangeDependencies() {
if (isInit) {
final productid = ModalRoute.of(context)!.settings.arguments as String;
if (productid != null) {
editProduct =
Provider.of<Products>(context, listen: false).findById(productid);
initValues = {
'title': editProduct.title,
'description': editProduct.desc,
'price': editProduct.price.toString(),
'imageUrl': '',
};
imageControl.text = editProduct.imageUrl;
}
}
isInit = false;
super.didChangeDependencies();
}
So you can just cast to a nullable string and I think your problem is solved
final productid = ModalRoute.of(context)!.settings.arguments as String?;