在颤振中通过 Function(T) 传递泛型类型
Posted
技术标签:
【中文标题】在颤振中通过 Function(T) 传递泛型类型【英文标题】:passing generic type by Function(T) in flutter 【发布时间】: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()
【问题讨论】:
【参考方案1】:您使用泛型类型T
的方式不完整。 StateFullConsumerWidget
和 _StateFullConsumerWidgetState
类在您的代码中编写的关系是这样的:StateFullConsumerWidget
使用与其自身相同的 T
类型参数创建其状态,因此小部件知道该状态使用相同的泛型类型确实如此。但是,从_StateFullConsumerWidgetState
的角度来看,该类是这样声明的:
class _StateFullConsumerWidgetState<T extends ChangeNotifier>
extends State<StateFullConsumerWidget>
问题是状态类使用StateFullConsumerWidget
的一般形式,因此_StateFullConsumerWidgetState
作为类型参数接收的T
与StateFullConsumerWidget
是T
之间没有明确的关系使用。 Dart 不知道如何调和这种模棱两可的关系,因此它默认使用类型约束允许的最小公分母,即ChangeNotifier
。
因此,当您尝试将T
视为OnBoardingViewModel
时,Dart 会抛出错误,因为据状态类所知,父窗口小部件的T
是ChangeNotifier
,而不是@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,
),
);
【讨论】:
以上是关于在颤振中通过 Function(T) 传递泛型类型的主要内容,如果未能解决你的问题,请参考以下文章