【问题标题】:The argument type 'Products Function(BuildContext, dynamic, dynamic)' can't be assigned to the parameter type 'Products Function(BuildContext)'参数类型“产品函数(BuildContext,动态,动态)”不能分配给参数类型“产品函数(BuildContext)”
【发布时间】:2021-09-30 02:43:19
【问题描述】:

我是一个新学习者,学习了以前版本中编写的 Flutter 教程,我收到以下代码错误:

main.ts:

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider.value(
          value: Auth(),
        ),
        ChangeNotifierProxyProvider<Auth, Products>(
          create: (ctx, auth, previousProducts) => Products(
            auth.token,
            auth.userId,
            previousProducts == null ? [] : previousProducts.items,
          ),
        ),
        ChangeNotifierProvider.value(
          value: Cart(),
        ),
        ChangeNotifierProxyProvider<Auth, Orders>(
          create: (ctx, auth, previousOrders) => Orders(
            auth.token,
            auth.userId,
            previousOrders == null ? [] : previousOrders.orders,
          ),
        ),
      ],
      child: Consumer<Auth>(
        builder: (ctx, auth, _) => MaterialApp(
          title: 'MyShop',
          theme: ThemeData(
            primarySwatch: Colors.purple,
            textSelectionTheme: TextSelectionThemeData(
              selectionColor: Colors.deepOrange,
              selectionHandleColor: Colors.blue,
            ),
            fontFamily: 'Lato',
            pageTransitionsTheme: PageTransitionsTheme(
              builders: {
                TargetPlatform.android: CustomPageTransitionBuilder(),
                TargetPlatform.iOS: CustomPageTransitionBuilder(),
              },
            ),
          ),
          home: auth.isAuth
              ? ProductsOverviewScreen()
              : FutureBuilder(
                  future: auth.tryAutoLogin(),
                  builder: (ctx, authResultSnapshot) =>
                      authResultSnapshot.connectionState ==
                              ConnectionState.waiting
                          ? SplashScreen()
                          : AuthScreen(),
                ),
          routes: {
            ProductDetailScreen.routeName: (ctx) => ProductDetailScreen(),
            CartScreen.routeName: (ctx) => CartScreen(),
            OrdersScreen.routeName: (ctx) => OrdersScreen(),
            UserProductsScreen.routeName: (ctx) => UserProductsScreen(),
            EditProductScreen.routeName: (ctx) => EditProductScreen(),
          },
        ),
      ),
    );
  }
}

命名参数'update'是必需的,但没有对应的 争论。尝试添加所需的参数。

参数类型'Products Function(BuildContext, dynamic, dynamic)' 不能分配给参数类型“产品” 函数(BuildContext)'。

所有错误都来自这部分代码(以及其他类似部分):

ChangeNotifierProxyProvider<Auth, Products>(
  create: (ctx, auth, previousProducts) => Products(
    auth.token,
    auth.userId,
    previousProducts == null ? [] : previousProducts.items,
  ),

这是 Products.ts:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

import '../models/http_exception.dart';
import './product.dart';

class Products with ChangeNotifier {
  List<Product> _items = [];
  final String authToken;
  final String userId;

  Products(this.authToken, this.userId, this._items);

  List<Product> get items {
    // if (_showFavoritesOnly) {
    //   return _items.where((prodItem) => prodItem.isFavorite).toList();
    // }
    return [..._items];
  }

  List<Product> get favoriteItems {
    return _items.where((prodItem) => prodItem.isFavorite).toList();
  }

  Product findById(String id) {
    return _items.firstWhere((prod) => prod.id == id);
  }


  Future<void> fetchAndSetProducts([bool filterByUser = false]) async {
    final filterString =
        filterByUser ? 'orderBy="creatorId"&equalTo="$userId"' : '';
    var url = Uri.parse(
        'https://flutter-update.firebaseio.com/products.json?auth=$authToken&$filterString');
    try {
      final response = await http.get(url);
      final extractedData = json.decode(response.body) as Map<String, dynamic>;
      if (extractedData == null) {
        return;
      }
      url = Uri.parse(
          'https://flutter-update.firebaseio.com/userFavorites/$userId.json?auth=$authToken');
      final favoriteResponse = await http.get(url);
      final favoriteData = json.decode(favoriteResponse.body);
      final List<Product> loadedProducts = [];
      extractedData.forEach((prodId, prodData) {
        loadedProducts.add(Product(
          id: prodId,
          title: prodData['title'],
          description: prodData['description'],
          price: prodData['price'],
          isFavorite:
              favoriteData == null ? false : favoriteData[prodId] ?? false,
          imageUrl: prodData['imageUrl'],
        ));
      });
      _items = loadedProducts;
      notifyListeners();
    } catch (error) {
      throw (error);
    }
  }

  Future<void> addProduct(Product product) async {
    final url = Uri.parse(
        'https://flutter-update.firebaseio.com/products.json?auth=$authToken');
    try {
      final response = await http.post(
        url,
        body: json.encode({
          'title': product.title,
          'description': product.description,
          'imageUrl': product.imageUrl,
          'price': product.price,
          'creatorId': userId,
        }),
      );
      final newProduct = Product(
        title: product.title,
        description: product.description,
        price: product.price,
        imageUrl: product.imageUrl,
        id: json.decode(response.body)['name'],
      );
      _items.add(newProduct);
      // _items.insert(0, newProduct); // at the start of the list
      notifyListeners();
    } catch (error) {
      print(error);
      throw error;
    }
  }

  Future<void> updateProduct(String id, Product newProduct) async {
    final prodIndex = _items.indexWhere((prod) => prod.id == id);
    if (prodIndex >= 0) {
      final url = Uri.parse(
          'https://flutter-update.firebaseio.com/products/$id.json?auth=$authToken');
      await http.patch(url,
          body: json.encode({
            'title': newProduct.title,
            'description': newProduct.description,
            'imageUrl': newProduct.imageUrl,
            'price': newProduct.price
          }));
      _items[prodIndex] = newProduct;
      notifyListeners();
    } else {
      print('...');
    }
  }

  Future<void> deleteProduct(String id) async {
    final url = Uri.parse(
        'https://flutter-update.firebaseio.com/products/$id.json?auth=$authToken');
    final existingProductIndex = _items.indexWhere((prod) => prod.id == id);
    Product? existingProduct = _items[existingProductIndex];
    _items.removeAt(existingProductIndex);
    notifyListeners();
    final response = await http.delete(url);
    if (response.statusCode >= 400) {
      _items.insert(existingProductIndex, existingProduct);
      notifyListeners();
      throw HttpException('Could not delete product.');
    }
    existingProduct = null;
  }
}

我不知道是什么问题,我应该如何解决这些错误?我在Products 类中找不到名为update 的必需参数。

【问题讨论】:

    标签: flutter typeerror non-nullable


    【解决方案1】:

    我假设您正在学习 Maximillian 的 udemy 课程。您正在使用 ChangeNotifierProxy,因为您的 Products 提供者依赖于 Auth 提供者的变量。

    ChangeNotifierProxyProvider<MyModel, MyChangeNotifier>(
    create: (_) => MyChangeNotifier(),
    update: (_, myModel, myNotifier) => myNotifier
    ..update(myModel),
    child: ...
    );
    

    这是定义 ChangeNotifierProxyProvider 的方法。 在您的情况下,它将是:

    没有 null 安全迁移

             ChangeNotifierProxyProvider<Auth, Products>(
             create: null,
             update: (context, auth, previousProducts) => Products(auth.token,
             previousProducts == null ? [] : previousProducts.items, 
             auth.userId)),
    

    使用 null 安全迁移

             ChangeNotifierProxyProvider<Auth, Products>(
             create: (ctx) => Products('', '', []),
             update: (context, auth, previousProducts) => 
             Products(auth.token,previousProducts.items,auth.userId)),
    

    如果您看到任何与更新相关的错误,那么您需要升级您的软件包。

    如果您还需要帮助,请告诉我 :)

    【讨论】:

    • 谢谢Sharib,是的,我正在使用该教程课程并按照您在代码中的建议进行操作,但它并没有解决我的问题,我仍然收到此错误消息:The argument type 'Null' can't be assigned to the parameter type 'Products Function(BuildContext)'. 对于这一行代码create: null,
    • 抱歉回复晚了。请参阅更新的答案。 @ensan3kamel
    • 没问题!我可以像我写的那样解决这个问题作为一个新的答案,但我仍然有兴趣知道我所做的和你的建议之间是否有任何区别。使用空变量初始化变量(如您所建议的那样)或为它们分配 null 值(如我所做的那样)之间有什么区别吗?
    • 您所做的一切都是不必要的,因为您的项目默认迁移为空安全,并且也不需要类型转换。请查看我的更新答案。
    【解决方案2】:

    不要使用ChangeNotifierProxyProvider 创建新对象。这是一个提供者,它也依赖于其他对象来更新它的值。通过以下方式仅使用Provider

    Provider(
      create: (_) => MyModel(),
      child: ...
    )
    
    

    这对于您的用例应该足够了。

    【讨论】:

    • 我想将一个提供者的数据传递给另一个提供者。所以我使用了 ChangeNotifierProxyProvider 。
    【解决方案3】:

    最后我可以通过修改代码来解决我的问题:

    providers: [
            ChangeNotifierProvider.value(
              value: Auth(),
            ),
            ChangeNotifierProxyProvider<Auth, Products>(
              create: (ctx) =>
                  Products(null as String, null as String, null as List<Product>),
              update: (ctx, auth, previousProducts) => Products(
                auth.token as String,
                auth.userId as String,
                previousProducts == null ? [] : previousProducts.items,
              ),
            ),
            ChangeNotifierProvider.value(
              value: Cart(),
            ),
            ChangeNotifierProxyProvider<Auth, Orders>(
              create: (ctx) =>
                  Orders(null as String, null as String, null as  List<OrderItem>),
              update: (ctx, auth, previousOrders) => Orders(
                auth.token as String,
                auth.userId as String,
                previousOrders == null ? [] : previousOrders.orders,
              ),
            ),
          ],
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-12
      • 2020-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-17
      相关资源
      最近更新 更多