在 flutter 中通过 Function(T) 传递泛型

passing generic type by Function(T) in flutter

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

在通用 class 中是 ChangeNotifier 的子项,在我想在两个函数中发送 T 值之前它工作正常。

然后我得到以下错误:

type '(OnBoardingViewModel) => Null' is not a subtype of type '(ChangeNotifier) => void'

type '(BuildContext, OnBoardingViewModel, Widget) => Scaffold' is not a subtype of type '(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(){

  }
}

我不太确定为什么会这样,但 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,
      ),
    );
  }
}

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

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

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

因此,当您尝试将 T 视为 OnBoardingViewModel 时,Dart 会抛出错误,因为就状态 class 而言,T父小部件的是 ChangeNotifier,而不是 OnBoardingViewModel

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

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