When I click on edit product on my app, it must go to the EditProductScreen where I can edit it, but this error appears (see also the photo):
Tried to call Provider.of<dynamic>. This is likely a mistake and is therefore unsupported.
If you want to expose a variable that can be anything, consider changing `dynamic` to `Object` instead. ‘package:provider/src/provider.dart’: Failed assertion: line 330 pos 7: ‘T != dynamic’
here are the EditProductScreen (a stateful class) codes :
import 'package:flutter/material.dart';
import 'package:my_shop/providers/product.dart';
import 'package:my_shop/providers/products.dart';
import 'package:provider/provider.dart';
class EditProductScreen extends StatefulWidget {
static const routeName = '/edit-product';
@override
State<EditProductScreen> createState() => _EditProductScreenState();
}
class _EditProductScreenState extends State<EditProductScreen> {
final _priceFocusNode = FocusNode();
final _descriptionFocusNode = FocusNode();
final _imageUrlFocusNode = FocusNode();
final _imageUrlController = TextEditingController();
final _form = GlobalKey<FormState>();
var _editedProduct =
Product(id: '', title: '', description: '', price: 0.0, imageUrl: '');
var _initValues = {
'title': '',
'description': '',
'price': '',
'imageUrl': '',
};
var _isInit = true;
@override
void initState() {
_imageUrlFocusNode.addListener(_updateImageUrl);
super.initState();
}
@override
void didChangeDependencies() {
if (_isInit) {
final productId = ModalRoute.of(context)!.settings.arguments as String?;
if (productId != null) {
_editedProduct =
Provider.of(context, listen: false).findById(productId);
_initValues = {
'title': _editedProduct.title,
'description': _editedProduct.description,
'price': _editedProduct.price.toString(),
//'imageUrl': _editedProduct.imageUrl,
'imageUrl': '',
};
_imageUrlController.text = _editedProduct.imageUrl;
}
_isInit = false;
}
super.didChangeDependencies();
}
@override
void dispose() {
_imageUrlFocusNode.removeListener(_updateImageUrl);
_priceFocusNode.dispose();
_descriptionFocusNode.dispose();
_imageUrlFocusNode.dispose();
_imageUrlController.dispose();
super.dispose();
}
void _updateImageUrl() {
if (_imageUrlFocusNode.hasFocus) {
setState(() {});
}
if ((!_imageUrlController.text.startsWith('http') &&
!_imageUrlController.text.startsWith('https')) ||
(!_imageUrlController.text.endsWith('png') &&
!_imageUrlController.text.endsWith('jpg') &&
!_imageUrlController.text.endsWith('jpeg'))) {
return;
}
}
void _saveForm() {
_form.currentState!.save();
if (_editedProduct.id != '') {
Provider.of<Products>(context)
.updateProduct(_editedProduct.id, _editedProduct);
} else {
Provider.of<Products>(context, listen: false).addProduct(_editedProduct);
}
Navigator.of(context).pop();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('edit product'),
actions: <Widget>[
IconButton(
onPressed: _saveForm,
icon: const Icon(Icons.save),
)
],
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _form,
child: ListView(
children: <Widget>[
TextFormField(
initialValue: _initValues['title'],
decoration: const InputDecoration(labelText: 'Title'),
textInputAction: TextInputAction.next,
onFieldSubmitted: (_) {
FocusScope.of(context).requestFocus(_priceFocusNode);
},
validator: (value) {
if (value!.isEmpty) {
return 'Please enter a valid value!';
}
return null;
},
onSaved: (value) {
_editedProduct = Product(
id: _editedProduct.id,
isFavorite: _editedProduct.isFavorite,
title: value ?? '',
description: _editedProduct.description,
price: _editedProduct.price,
imageUrl: _editedProduct.imageUrl);
},
),
TextFormField(
initialValue: _initValues['price'],
decoration: const InputDecoration(labelText: 'Price'),
textInputAction: TextInputAction.next,
keyboardType: TextInputType.number,
focusNode: _priceFocusNode,
onFieldSubmitted: (_) {
FocusScope.of(context).requestFocus(_descriptionFocusNode);
},
validator: (value) {
if (value!.isEmpty) {
return 'Please enter a valid price!';
}
if (double.tryParse(value) == null) {
return 'Please enter a valid number!';
}
if (double.parse(value) <= 0) {
return 'Please Enter a number greater than zero!';
}
return null;
},
onSaved: (value) {
_editedProduct = Product(
id: _editedProduct.id,
isFavorite: _editedProduct.isFavorite,
title: _editedProduct.title,
description: _editedProduct.description,
price: double.parse(value ?? ''),
imageUrl: _editedProduct.imageUrl);
},
),
TextFormField(
initialValue: _initValues['description'],
decoration: const InputDecoration(labelText: 'Description'),
maxLines: 3,
textInputAction: TextInputAction.next,
keyboardType: TextInputType.multiline,
focusNode: _descriptionFocusNode,
validator: (value) {
if (value!.isEmpty) {
return 'Please enter a description';
}
if (value.length < 10) {
return 'Should be at least 10 characters long!';
}
return null;
},
onSaved: (value) {
_editedProduct = Product(
id: _editedProduct.id,
isFavorite: _editedProduct.isFavorite,
title: _editedProduct.title,
description: value ?? '',
price: _editedProduct.price,
imageUrl: _editedProduct.imageUrl);
},
),
Row(
children: <Widget>[
Container(
width: 100,
height: 100,
margin: const EdgeInsets.only(top: 8, right: 10),
decoration: BoxDecoration(
border: Border.all(width: 1, color: Colors.grey)),
child: _imageUrlController.text.isEmpty
? const Text('Enter a URL!')
: FittedBox(
child: Image.network(_imageUrlController.text),
fit: BoxFit.cover,
)),
Expanded(
child: TextFormField(
decoration:
const InputDecoration(labelText: 'Image URL'),
keyboardType: TextInputType.url,
textInputAction: TextInputAction.done,
controller: _imageUrlController,
focusNode: _imageUrlFocusNode,
validator: (value) {
if (value!.isEmpty) {
return 'Please enter a valid image URL!';
}
if (!value.startsWith('http') &&
!value.startsWith('https')) {
return 'Please enter a valid URL!';
}
if (!value.endsWith('png') &&
!value.endsWith('jpg') &&
!value.endsWith('jpeg')) {
return 'Please enter a valid image type!';
}
return null;
},
onSaved: (value) {
_editedProduct = Product(
id: _editedProduct.id,
isFavorite: _editedProduct.isFavorite,
title: _editedProduct.title,
description: _editedProduct.description,
price: _editedProduct.price,
imageUrl: value ?? '');
},
onFieldSubmitted: (_) {
_saveForm();
},
),
),
],
)
],
)),
),
);
}
}
>Solution :
Might be this. give the provider class. Try this
Provider.of<Products>(context, listen: false).findById(productId);
