预期的值应为“字符串类型”,但得到了“空类型”的值。

5

我需要在一个屏幕上添加新产品并编辑现有的产品。所以我使用了didchangedependencies方法,通过分配初始值来更新屏幕,在我的代码中出了点问题,请帮帮我。错误如下:

enter image description here

错误显示在这里:

@override
      void didChangeDependencies() {
        if (_isinit) {
          final productId = ModalRoute.of(context)!.settings.arguments as String;

      // ignore: unnecessary_null_comparison
      if (productId != null) {
        _editedproduct =
            Provider.of<Products>(context, listen: false).FindByID(productId);
        _imageUrlController.text = _editedproduct.imageUrl;
        _initValues = {
          'title': _editedproduct.title,
          'description': _editedproduct.description,
          'Price': _editedproduct.price.toString(),
          // 'imageUrl': _editedproduct.imageUrl,
          'imageUrl': '',
        };
      }
    }
    _isinit = false;
    super.didChangeDependencies();
  } 

在 didChangeDependencies 方法中,我尝试从一个页面获取参数,即产品 ID,但它显示为空。这是一个屏幕截图,我已经将其推送到编辑产品页面,并尝试获取这些参数。
enter image description here
这是用于推送添加产品页面的内容。 enter image description here
import 'dart:html';

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shoppingapp/Providers/Product.dart';
import 'package:shoppingapp/Providers/Products.dart';

class EditProductScreen extends StatefulWidget {
  static const routeName = '/edit-products';
  @override
  _EditProductScreenState createState() => _EditProductScreenState();
}

class _EditProductScreenState extends State<EditProductScreen> {
  final _priceFocusNode = FocusNode();
  final _descriptionFocusNode = FocusNode();
  final _imageUrlController = TextEditingController();
  final _imageUrlFocusNode = FocusNode();
  final _form = GlobalKey<FormState>();
  var _editedproduct =
      Product(id: '', title: '', description: '', price: 0, imageUrl: '');
  var _isinit = true;

  var _initValues = {
    'title': '',
    'description': '',
    'price': '',
    'imageUrl': '',
  };
  @override
  void initState() {
    _imageUrlFocusNode.addListener(_updateImageUrl);
    super.initState();
  }

  @override
  void didChangeDependencies() {
    if (_isinit) {
      final productId = ModalRoute.of(context)!.settings.arguments as String;

      // ignore: unnecessary_null_comparison
      if (productId != null) {
        _editedproduct =
            Provider.of<Products>(context, listen: false).FindByID(productId);
        _imageUrlController.text = _editedproduct.imageUrl;
        _initValues = {
          'title': _editedproduct.title,
          'description': _editedproduct.description,
          'Price': _editedproduct.price.toString(),
          // 'imageUrl': _editedproduct.imageUrl,
          'imageUrl': '',
        };
      }
    }
    _isinit = false;
    super.didChangeDependencies();
  }

  @override
  void dispose() {
    _imageUrlFocusNode.removeListener(_updateImageUrl);
    _priceFocusNode.dispose();
    _descriptionFocusNode.dispose();
    _imageUrlFocusNode.dispose();

    super.dispose();
  }

  void _updateImageUrl() {
    if (!_imageUrlFocusNode.hasFocus) {
      setState(() {});
    }
  }

  void _saveForm() {
    final isValid = _form.currentState!.validate();
    if (isValid) {
      return;
    }
    _form.currentState!.save();
    if (_editedproduct.id != null) {
      Provider.of<Products>(context, listen: false)
          .updateProducts(_editedproduct.id, _editedproduct);
    } else {
      Provider.of<Products>(context, listen: false).addProducts(_editedproduct);
    }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Edit Product'),
        actions: [
          IconButton(
            icon: Icon(Icons.save),
            onPressed: _saveForm,
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(15.0),
        child: Form(
          key: _form,
          child: ListView(
            children: [
              TextFormField(
                decoration: InputDecoration(
                  labelText: 'Title',
                ),
                initialValue: _initValues['title'],
                textInputAction: TextInputAction.next,
                validator: (value) {
                  if (value!.isEmpty) {
                    return 'Please provide a value.';
                  }
                  return null;
                },
                onFieldSubmitted: (_) {
                  FocusScope.of(context).requestFocus(_priceFocusNode);
                },
                onSaved: (value) {
                  _editedproduct = Product(
                      title: value as String,
                      price: _editedproduct.price,
                      description: _editedproduct.description,
                      imageUrl: _editedproduct.imageUrl,
                      id: _editedproduct.id,
                      isFavourite: _editedproduct.isFavourite);
                },
              ),
              TextFormField(
                initialValue: _initValues['price'],
                decoration: InputDecoration(
                  labelText: 'Price',
                ),
                textInputAction: TextInputAction.next,
                keyboardType: TextInputType.number,
                focusNode: _priceFocusNode,
                validator: (value) {
                  if (value!.isEmpty) {
                    return 'Please enter a  price ';
                  }
                  if (double.tryParse(value) == null) {
                    return 'Please Enter a Valid Number';
                  }
                  if (double.parse(value) <= 0) {
                    return 'Please Enter the number greather no than zero';
                  }
                },
                onSaved: (value) {
                  _editedproduct = Product(
                      title: _editedproduct.title,
                      price: double.parse(value!),
                      description: _editedproduct.description,
                      imageUrl: _editedproduct.imageUrl,
                      id: _editedproduct.id,
                      isFavourite: _editedproduct.isFavourite);
                },
              ),
              TextFormField(
                decoration: InputDecoration(
                  labelText: 'Description',
                ),
                initialValue: _initValues['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(
                      title: _editedproduct.title,
                      price: _editedproduct.price,
                      description: value as String,
                      imageUrl: _editedproduct.imageUrl,
                      id: _editedproduct.id,
                      isFavourite: _editedproduct.isFavourite);
                },
              ),
              Row(
                crossAxisAlignment: CrossAxisAlignment.end,
                children: [
                  Container(
                    width: 100,
                    height: 100,
                    margin: EdgeInsets.only(top: 8, right: 10),
                    decoration: BoxDecoration(
                        border: Border.all(width: 1, color: Colors.grey)),
                    child: _imageUrlController.text.isEmpty
                        ? Text('Enter a URL')
                        : FittedBox(
                            child: Image.network(
                              _imageUrlController.text,
                              fit: BoxFit.cover,
                            ),
                          ),
                  ),
                  Expanded(
                    child: TextFormField(
                      decoration: InputDecoration(labelText: 'Image URl'),
                      keyboardType: TextInputType.url,
                      textInputAction: TextInputAction.done,
                      controller: _imageUrlController,
                      focusNode: _imageUrlFocusNode,
                      validator: (value) {
                        if (value!.isEmpty) {
                          return 'Please enter a  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 URL';
                        }
                        return null;
                      },
                      onFieldSubmitted: (_) {
                        _saveForm();
                      },
                      onSaved: (value) {
                        _editedproduct = Product(
                            title: _editedproduct.title,
                            price: _editedproduct.price,
                            description: _editedproduct.description,
                            imageUrl: value as String,
                            id: _editedproduct.id,
                            isFavourite: _editedproduct.isFavourite);
                      },
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

你知道哪个变量是空的吗? - Jitesh Mohite
我认为在didchangedependencies方法中,ProductID变量 - Rex
1
你已经添加了空值检查 if (productId != null),现在你不应该再遇到那个异常了。 - Jitesh Mohite
这是因为_initvalues中的imageurl吗? - Rex
1
我怀疑_editedproduct提供的值不全,建议使用空值运算符升级Flutter。 - Jitesh Mohite
我尝试打印_editedproduct的每个变量,但它完美地运行了。 - Rex
5个回答

4

尽管空安全性已经实现,但大多数教程都是在此之前制作的。因此,在您尝试检查ModalRoute是否返回null值并根据此执行操作的情况下,好像老式的if(productId == null)现在行不通了。 相反,您可以这样做:

final productId = ModalRoute.of(context)!.settings.arguments == null ? "NULL":ModalRoute.of(context)!.settings.arguments as String;

if(productId != "NULL"){
 
   //Do stuff here

}

如果 ModalRoute 返回 null,则将字符串 "NULL" 赋值给变量 productId,否则将其返回的任何值直接赋值给该变量。
然后,你可以简单地检查 productId 的值是否为 NULL 并相应地进行处理。

2

根据Maruf Ahmed的回答,代码可以运行但是无法显示添加的产品。对我而言解决错误的方法是在saveForm方法中将!= null更改为''注释。

您可以检查saveForm方法。

1


代码片段应该作为正确格式的文本包含,而不是作为图像。您可以在帮助中心找到有关如何编写好答案的更多信息。 - YurkoFlisk

1

在我的情况下,错误与堆栈跟踪相同

Error: Expected a value of type 'String', but got one of type 'Null'
    at Object.throw_ [as throw] (http://localhost:51932/dart_sdk.js:5080:11)
    at Object.castError (http://localhost:51932/dart_sdk.js:5039:15)
    at Object.cast [as as] (http://localhost:51932/dart_sdk.js:5356:17)
    at String.as (http://localhost:51932/dart_sdk.js:46240:19)
    at Object.getProperty (http://localhost:51932/dart_sdk.js:62320:14)
    at Object.convertFirebaseDatabaseException (http://localhost:51932/packages/firebase_database_web/src/interop/database.dart.lib.js:1318:27)
    at http://localhost:51932/packages/firebase_database_web/src/interop/database.dart.lib.js:289:67
    at Object._checkAndCall (http://localhost:51932/dart_sdk.js:5279:16)
    at Object.dcall (http://localhost:51932/dart_sdk.js:5284:17)
    at ret (http://localhost:51932/dart_sdk.js:62210:21)
    at CallbackContext.onCancel (https://www.gstatic.com/firebasejs/9.9.0/firebase-database.js:13442:36)
    at https://www.gstatic.com/firebasejs/9.9.0/firebase-database.js:14240:47
    at exceptionGuard (https://www.gstatic.com/firebasejs/9.9.0/firebase-database.js:2000:9)
    at eventListRaise (https://www.gstatic.com/firebasejs/9.9.0/firebase-database.js:12292:13)
    at eventQueueRaiseQueuedEventsMatchingPredicate (https://www.gstatic.com/firebasejs/9.9.0/firebase-database.js:12267:17)
    at eventQueueRaiseEventsForChangedPath (https://www.gstatic.com/firebasejs/9.9.0/firebase-database.js:12256:5)
    at Object.onComplete (https://www.gstatic.com/firebasejs/9.9.0/firebase-database.js:12413:17)
    at https://www.gstatic.com/firebasejs/9.9.0/firebase-database.js:4667:32
    at PersistentConnection.onDataMessage_ (https://www.gstatic.com/firebasejs/9.9.0/firebase-database.js:4920:17)
    at Connection.onDataMessage_ (https://www.gstatic.com/firebasejs/9.9.0/firebase-database.js:3762:14)
    at Connection.onPrimaryMessageReceived_ (https://www.gstatic.com/firebasejs/9.9.0/firebase-database.js:3756:18)
    at WebSocketConnection.onMessage (https://www.gstatic.com/firebasejs/9.9.0/firebase-database.js:3658:26)
    at WebSocketConnection.appendFrame_ (https://www.gstatic.com/firebasejs/9.9.0/firebase-database.js:3275:18)
    at WebSocketConnection.handleIncomingFrame (https://www.gstatic.com/firebasejs/9.9.0/firebase-database.js:3323:22)
    at mySock.onmessage (https://www.gstatic.com/firebasejs/9.9.0/firebase-database.js:3222:18)

我被这个问题困扰了两天,后来想起默认数据库规则的日期限制已经过期了:

{
  "rules": {
    ".read": "now < ...",  // YYYY-MM-DD
    ".write": "now < ...",  // YYYY-MM-DD
  }
}

所以我刚刚定义了更好的规则,现在它可以正常工作了。


1

我知道回答这个问题有点晚,但我的回答将会帮助到未来的某个人。

避免将参数转换为字符串。当调用pushname时没有传递任何参数时,它会自动传递null,当将null强制转换为字符串时就会出现错误。

请使用以下代码:

final productId= ModalRoute.of(context)!.settings.arguments;

检查productId是否为null。如果不是null,则将产品对象转换为字符串。
  if (productId != null) {
    _editedProduct =
        Provider.of<Products>(context, listen: false).findById(productId.toString());
    ...... 

  }

-2

Jitesh Mohite (_editedProduct.id) 是在 'build' 内部的 null 变量,在 'didchangedependencies' 内部它不是 null,它具有 ProductId 的相同值


这并没有回答问题,请在问题的评论中提出您的疑问。 - Wilfred Almeida

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接