【问题标题】:passing generic type by Function(T) in flutter在颤振中通过 Function(T) 传递泛型类型
【发布时间】:2020-01-13 03:32:59
【问题描述】:

我正在尝试创建一个通用的消费者小部件,以方便其子视图模型。因此我有两个功能。一个在 ViewModel 初始化后具有函数(T),另一个用于将模型传递给其子 Widget。

在泛型类中是 ChangeNotifier 的子类,它工作正常,直到我想在两个函数中发送 T 值。

然后我收到以下错误:

type '(OnBoardingViewModel) => Null' 不是 type 的子类型 '(ChangeNotifier) => 无效'

type '(BuildContext, OnBoardingViewModel, Widget) => Scaffold' 不是 类型的子类型 '(BuildContext, ChangeNotifier, Widget) => Widget'

但是当我将扩展类型从 ChangeNotifier 更改为 OnBoardingViewModel 时,一切正常。

有人可以帮助我或解释为什么这不起作用吗?

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

class StateFullConsumerWidget<T extends ChangeNotifier> extends StatefulWidget{

  StateFullConsumerWidget({@required this.builder,Key key,this.onPostViewModelInit,this.child}) : super(key : key);

  final Widget Function(BuildContext context, ChangeNotifier value, Widget child) builder;
  final Widget child;

  final void Function(T) onPostViewModelInit;

  @override
  _StateFullConsumerWidgetState<T> createState() => _StateFullConsumerWidgetState<T>();
}

class _StateFullConsumerWidgetState<T extends ChangeNotifier> extends State<StateFullConsumerWidget>{
  T _viewModel;
  @override
  void initState() {
    // assign the model once when state is initialised
    _viewModel = GetIt.instance.get<T>();
    widget.onPostViewModelInit(_viewModel);


    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<T>(
      builder: (context) => _viewModel,
      child: Consumer<T>(
        builder: widget.builder,
        child: widget.child,
      ),
    );
  }

}

我的小部件

StateFullConsumerWidget<OnBoardingViewModel>(
      onPostViewModelInit: (viewModel){
        buildIntroList(viewModel);
        viewModel.maxPages = _introWidgetsList.length;
      },
      builder: (context,viewModel,child) {
        return Scaffold(
          key: widget.scaffoldKey,
          body: SafeArea(
            child: Container(),
            ),
          ),
        );
      },
    );

我的视图模型

import 'package:flutter/material.dart';

class OnBoardingViewModel extends ChangeNotifier{

  OnBoardingViewModel(){

  }
}

【问题讨论】:

    标签: generics flutter dart flutter-widget


    【解决方案1】:

    您使用泛型类型T 的方式不完整。 StateFullConsumerWidget_StateFullConsumerWidgetState 类在您的代码中编写的关系是这样的:StateFullConsumerWidget 使用与其自身相同的 T 类型参数创建其状态,因此小部件知道该状态使用相同的泛型类型确实如此。但是,从_StateFullConsumerWidgetState 的角度来看,该类是这样声明的:

    class _StateFullConsumerWidgetState<T extends ChangeNotifier> 
        extends State<StateFullConsumerWidget>
    

    问题是状态类使用StateFullConsumerWidget的一般形式,因此_StateFullConsumerWidgetState作为类型参数接收的TStateFullConsumerWidgetT之间没有明确的关系使用。 Dart 不知道如何调和这种模棱两可的关系,因此它默认使用类型约束允许的最小公分母,即ChangeNotifier

    因此,当您尝试将T 视为OnBoardingViewModel 时,Dart 会抛出错误,因为据状态类所知,父窗口小部件的TChangeNotifier,而不是@987654338 @。

    您可以通过在声明状态类时传递类型参数来解决此问题:

    class _StateFullConsumerWidgetState<T extends ChangeNotifier> 
        extends State<StateFullConsumerWidget<T>>
    

    【讨论】:

      【解决方案2】:

      我不确定为什么会这样,但是 dart 编译器无法将 StateFullConsumerWidget 中的类型 T 识别为 _StateFullConsumerWidgetState 的相同类型 T。如果你将函数传递给 State 一切都会按预期工作。

      结果代码:

      class StateFullConsumerWidget<T extends ChangeNotifier> extends StatefulWidget{
      
        StateFullConsumerWidget({@required this.builder,Key key,this.onPostViewModelInit,this.child}) : super(key : key);
      
        final Widget Function(BuildContext context, T value, Widget child) builder;
        final Widget child;
      
        final Function(T viewModel) onPostViewModelInit;
      
        @override
        _StateFullConsumerWidgetState<T> createState() => _StateFullConsumerWidgetState<T>(onPostViewModelInit, builder);
      }
      
      class _StateFullConsumerWidgetState<T extends ChangeNotifier> extends State<StateFullConsumerWidget>{
        final Function(T viewModel) _onPostViewModelInit;
        final Widget Function(BuildContext context, T value, Widget child) _builder;
        T _viewModel;
      
        _StateFullConsumerWidgetState(this._onPostViewModelInit, this._builder);
      
        @override
        void initState() {
          // assign the model once when state is initialised
          _viewModel = GetIt.instance.get<T>();
          _onPostViewModelInit(_viewModel);
          super.initState();
        }
      
        @override
        Widget build(BuildContext context) {
          return ChangeNotifierProvider<T>(
            builder: (context) => _viewModel,
            child: Consumer<T>(
              builder: _builder,
              child: widget.child,
            ),
          );
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-20
        • 2021-01-04
        • 2020-02-05
        • 2021-06-23
        • 2016-08-24
        • 1970-01-01
        相关资源
        最近更新 更多