Home > Back-end >  type 'Null' is not a subtype of type 'String' in type case
type 'Null' is not a subtype of type 'String' in type case

Time:06-27

What could be the possible reasons for this error, please guide.

This is my code

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../models/product.dart';
import '../provider/products.dart';

class EditProductScreen extends StatefulWidget {
  static const routeName = '/edite-product-screen';

  @override
  State<EditProductScreen> createState() => _EditProductScreenState();
}

class _EditProductScreenState extends State<EditProductScreen> {
  final priceFocusNode = FocusNode();
  final descriptionFocusNode = FocusNode();
  final imageURLController = TextEditingController();
  // TextEditingController listens to updates in the associated TextField and alert its listeners of any changes
  final imageURLFocusNode = FocusNode();
  final keyForForm = GlobalKey<FormState>();
  var emptyProduct =
      Product(id: "", title: "", description: "", price: 0, imageUrl: "");
  var isInit = true;

  var initValues = {
    'title': "",
    'description': "",
    'price': "",
    'imageURL': "",
  };

  @override
  void initState() {
    super.initState();
    imageURLFocusNode.addListener(updateImageUrl);
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    if (isInit) {
      final receivedProductID =
          ModalRoute.of(context)?.settings.arguments as String;
      if (receivedProductID != null) {
        emptyProduct = Provider.of<Products>(context, listen: false)
            .selectedProduct(receivedProductID);
        initValues = {
          'title': emptyProduct.title.toString(),
          'description': emptyProduct.description.toString(),
          'price': emptyProduct.price.toString(),
          // 'imageURL': "",
        };

        imageURLController.text = emptyProduct.imageUrl as String;
      }
    }

    isInit = false;
  }

  void updateImageUrl() {
    if (!imageURLFocusNode.hasFocus) {
      if ((!imageURLController.text.startsWith("http") &&
              !imageURLController.text.startsWith("https")) ||
          (!imageURLController.text.endsWith("jpg") &&
              !imageURLController.text.endsWith("png") &&
              !imageURLController.text.endsWith("jpeg")) ||
          (imageURLController.text.isEmpty)) {
        return;
      }
      setState(() {});
    }
  }

  void saveTheProductBasedOnInformationOfTheForm() {
    final validStatus = keyForForm.currentState?.validate();
    if (!validStatus!) {
      return;
    }

    keyForForm.currentState?.save();
    if (emptyProduct.id != null) {
      Provider.of<Products>(context, listen: false)
          .updateProduct(emptyProduct.id as String, emptyProduct);
    } else {
      Provider.of<Products>(context, listen: false).addProduct(emptyProduct);
    }

    Navigator.of(context).pop();
  }

  @override
  void dispose() {
    imageURLFocusNode.removeListener(updateImageUrl);
    priceFocusNode.dispose();
    descriptionFocusNode.dispose();
    imageURLController.dispose();
    imageURLFocusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Products"),
        actions: [
          IconButton(
              onPressed: saveTheProductBasedOnInformationOfTheForm,
              icon: Icon(Icons.save))
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
            key: keyForForm,
            child: ListView(
              children: [
                TextFormField(
                  initialValue: initValues['title'],
                  validator: (value) {
                    if (value!.isEmpty) {
                      return "Please enter a valid value";
                    } else {
                      return null;
                    }
                  },
                  decoration: InputDecoration(labelText: "Title"),
                  textInputAction: TextInputAction.next,
                  onFieldSubmitted: (_) => {
                    FocusScope.of(context).requestFocus(priceFocusNode),
                  },
                  onSaved: (value) {
                    emptyProduct = Product(
                        id: emptyProduct.id,
                        title: value,
                        description: emptyProduct.description,
                        price: emptyProduct.price,
                        imageUrl: emptyProduct.imageUrl,
                        isFavorite: emptyProduct.isFavorite);
                  },
                ),
                TextFormField(
                  initialValue: initValues['price'],
                  onSaved: (value) {
                    emptyProduct = Product(
                        id: emptyProduct.id,
                        title: emptyProduct.title,
                        description: emptyProduct.description,
                        price: double.parse(value as String),
                        imageUrl: emptyProduct.imageUrl,
                        isFavorite: emptyProduct.isFavorite);
                  },
                  decoration: 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 value greater than 0";
                    } else {
                      return null;
                    }
                  },
                ),
                TextFormField(
                  initialValue: initValues['description'],
                  onSaved: (value) {
                    emptyProduct = Product(
                        id: emptyProduct.id,
                        title: emptyProduct.title,
                        description: value,
                        price: emptyProduct.price,
                        imageUrl: emptyProduct.imageUrl,
                        isFavorite: emptyProduct.isFavorite);
                  },
                  decoration: InputDecoration(labelText: "Description"),
                  keyboardType: TextInputType.multiline,
                  maxLines: 3,
                  validator: (value) {
                    if (value!.isEmpty) {
                      return "Please enter a valid description";
                    }
                    if (value.length < 10) {
                      return "Please enter more description";
                    } else {
                      return null;
                    }
                  },
                ),
                Row(crossAxisAlignment: CrossAxisAlignment.end, children: [
                  Container(
                    width: 100,
                    height: 100,
                    margin: EdgeInsets.only(top: 10, right: 10),
                    decoration: BoxDecoration(
                        border: Border.all(width: 1, color: Colors.grey)),
                    child: imageURLController.text.isEmpty
                        ? Text("Please enter URL")
                        : Image.network(imageURLController.text),
                  ),
                  Expanded(
                    child: TextFormField(
                      initialValue: initValues['imageURL'],
                      validator: (value) {
                        if (value!.isEmpty) {
                          return "Please enter valid Image URL";
                        }
                        if ((!value.startsWith("http") &&
                                !value.startsWith("https")) ||
                            (!value.endsWith("jpg") &&
                                !value.endsWith("png") &&
                                !value.endsWith("jpeg"))) {
                          return "Please enter a valid URL!";
                        }
                      },
                      onSaved: (value) {
                        emptyProduct = Product(
                            id: emptyProduct.id,
                            title: emptyProduct.title,
                            description: emptyProduct.description,
                            price: emptyProduct.price,
                            imageUrl: value,
                            isFavorite: emptyProduct.isFavorite);
                      },
                      decoration: InputDecoration(labelText: "Image URL"),
                      keyboardType: TextInputType.url,
                      textInputAction: TextInputAction.done,
                      controller: imageURLController,
                      maxLines: 3,
                      focusNode: imageURLFocusNode,
                      onFieldSubmitted: (_) {
                        saveTheProductBasedOnInformationOfTheForm();
                      },
                    ),
                  ),
                ])
              ],
            )),
      ),
    );
  }
}

The screen opens without error when (receivedProductID != null), but shows the following error when (receivedProductID == null); see errror image

And when I try going back from the screen, I see this error see error image

What could be the possible reasons for this error, please guide.

CodePudding user response:

The reason for the first error is this type cast:

final receivedProductID = ModalRoute.of(context)?.settings.arguments as String;

You cast a nullable value to String. It should be String? instead because it can be null.

final receivedProductID =
      ModalRoute.of(context)?.settings.arguments as String?;
  • Related