Flutter 颤振:使用泛型创建小部件时出现子类型错误

Flutter 颤振:使用泛型创建小部件时出现子类型错误,flutter,flutter-provider,flutter-change-notifier,Flutter,Flutter Provider,Flutter Change Notifier,我正在为我的应用程序使用viewmodels来扩展ChangeNotifier。为了使用它们,我尝试实现一个通用的基本小部件: 类BasePageWidget 扩展StatefulWidget{ 最终函数(ViewModelType vm)初始化; 最终小部件功能(BuildContext上下文、ViewModelType vm)生成器; 最终视图模型类型_vm=sl.get(); BasePageWidget({Key-Key,this.init,this.builder}):super(K

我正在为我的应用程序使用viewmodels来扩展ChangeNotifier。为了使用它们,我尝试实现一个通用的基本小部件:


类BasePageWidget
扩展StatefulWidget{
最终函数(ViewModelType vm)初始化;
最终小部件功能(BuildContext上下文、ViewModelType vm)生成器;
最终视图模型类型_vm=sl.get();
BasePageWidget({Key-Key,this.init,this.builder}):super(Key:Key);
@凌驾
_BasePageWidgetState createState()=>\u BasePageWidgetState();
}
类_BasePageWidgetState
扩展状态{
@凌驾
小部件构建(构建上下文){
返回ChangeNotifierProvider.value(
值:widget.\u vm,
儿童:消费者(
builder:(context,widget.vm,child)=>widget.builder(context,widget.vm),
),
);
}
@凌驾
void initState(){
if(widget.init!=null){
widget.init(widget.\u vm);
}
super.initState();
}
}
基本小部件有一个类型参数,并使用get_it包的服务定位器获取viewmodel的实例

但是当我尝试运行应用程序时,当使用小部件时:

void main() {
  setup();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: BasePageWidget<ViewModel>(
        init: (vm) => vm.setTitle("Set init State"),
        builder: (context, vm) => FlatButton(
          onPressed: () {
            vm.setTitle("State2");
          },
          child: Text(vm.text),
        ),
      ),
    );
  }
}
这些错误似乎是由函数参数引起的:

final Function(ViewModelType vm) init;
final Widget Function(BuildContext context, ViewModelType vm) builder;
当我将泛型类型(ViewModelType)与dynamic交换时,应用程序运行良好(当然没有类型安全):

你知道如何使用通用参数运行它吗

下面是我的视图模型:

class ViewModel extends ChangeNotifier {
  String text = '';

  void setTitle(String text) {
    this.text = text;
    notifyListeners();
  }
}
以及get_it设置:

GetIt sl = GetIt.instance;

Future<void> setup() async {
  sl.registerFactory(() => ViewModel());
}
GetIt sl=GetIt.instance;
Future setup()异步{
sl.registerFactory(()=>ViewModel());
}

您可以复制粘贴运行下面的完整代码
请将
状态
更改为
状态

class\u BasePageWidgetState
扩展状态{

class\u BasePageWidgetState
扩展状态{
工作演示

完整代码

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

class BasePageWidget<ViewModelType extends ChangeNotifier>
    extends StatefulWidget {
  final Function(ViewModelType vm) init;
  final Widget Function(BuildContext context, ViewModelType vm) builder;
  final ViewModelType _vm = sl.get<ViewModelType>();

  BasePageWidget({Key key, this.init, this.builder}) : super(key: key);

  @override
  _BasePageWidgetState createState() => _BasePageWidgetState<ViewModelType>();
}

class _BasePageWidgetState<ViewModelType extends ChangeNotifier>
    extends State<BasePageWidget<ViewModelType>> {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<ViewModelType>.value(
      value: widget._vm,
      child: Consumer<ViewModelType>(
        builder: (context, _vm, child) => widget.builder(context, widget._vm),
      ),
    );
  }

  @override
  void initState() {
    if (widget.init != null) {
      widget.init(widget._vm);
    }
    super.initState();
  }
}

class ViewModel extends ChangeNotifier {
  String text = '';

  void setTitle(String text) {
    this.text = text;
    notifyListeners();
  }
}

GetIt sl = GetIt.instance;

Future<void> setup() async {
  sl.registerFactory(() => ViewModel());
}

void main() {
  setup();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: BasePageWidget<ViewModel>(
        init: (vm) => vm.setTitle("Set init State"),
        builder: (context, vm) => Scaffold(
          body: Center(
            child: FlatButton(
              onPressed: () {
                vm.setTitle("State2");
              },
              child: Text(vm.text),
            ),
          ),
        ),
      ),
    );
  }
}
导入“包装:颤振/材料.省道”;
导入“包:provider/provider.dart”;
导入“package:get_it/get_it.dart”;
类BasePageWidget
扩展StatefulWidget{
最终函数(ViewModelType vm)初始化;
最终小部件功能(BuildContext上下文、ViewModelType vm)生成器;
最终视图模型类型_vm=sl.get();
BasePageWidget({Key-Key,this.init,this.builder}):super(Key:Key);
@凌驾
_BasePageWidgetState createState()=>\u BasePageWidgetState();
}
类_BasePageWidgetState
扩展状态{
@凌驾
小部件构建(构建上下文){
返回ChangeNotifierProvider.value(
值:widget.\u vm,
儿童:消费者(
builder:(context,widget.vm,child)=>widget.builder(context,widget.vm),
),
);
}
@凌驾
void initState(){
if(widget.init!=null){
widget.init(widget.\u vm);
}
super.initState();
}
}
类ViewModel扩展了ChangeNotifier{
字符串文本=“”;
void setTitle(字符串文本){
this.text=文本;
notifyListeners();
}
}
GetIt sl=GetIt.instance;
Future setup()异步{
sl.registerFactory(()=>ViewModel());
}
void main(){
设置();
runApp(MyApp());
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“颤振演示”,
主页:BasePageWidget(
init:(vm)=>vm.setTitle(“设置初始化状态”),
生成器:(上下文,vm)=>Scaffold(
正文:中(
孩子:扁平按钮(
已按下:(){
vm.setTitle(“State2”);
},
子项:文本(vm.Text),
),
),
),
),
);
}
}
GetIt sl = GetIt.instance;

Future<void> setup() async {
  sl.registerFactory(() => ViewModel());
}
class _BasePageWidgetState<ViewModelType extends ChangeNotifier>
    extends State<BasePageWidget> {
class _BasePageWidgetState<ViewModelType extends ChangeNotifier>
extends State<BasePageWidget<ViewModelType>> {
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:get_it/get_it.dart';

class BasePageWidget<ViewModelType extends ChangeNotifier>
    extends StatefulWidget {
  final Function(ViewModelType vm) init;
  final Widget Function(BuildContext context, ViewModelType vm) builder;
  final ViewModelType _vm = sl.get<ViewModelType>();

  BasePageWidget({Key key, this.init, this.builder}) : super(key: key);

  @override
  _BasePageWidgetState createState() => _BasePageWidgetState<ViewModelType>();
}

class _BasePageWidgetState<ViewModelType extends ChangeNotifier>
    extends State<BasePageWidget<ViewModelType>> {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<ViewModelType>.value(
      value: widget._vm,
      child: Consumer<ViewModelType>(
        builder: (context, _vm, child) => widget.builder(context, widget._vm),
      ),
    );
  }

  @override
  void initState() {
    if (widget.init != null) {
      widget.init(widget._vm);
    }
    super.initState();
  }
}

class ViewModel extends ChangeNotifier {
  String text = '';

  void setTitle(String text) {
    this.text = text;
    notifyListeners();
  }
}

GetIt sl = GetIt.instance;

Future<void> setup() async {
  sl.registerFactory(() => ViewModel());
}

void main() {
  setup();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: BasePageWidget<ViewModel>(
        init: (vm) => vm.setTitle("Set init State"),
        builder: (context, vm) => Scaffold(
          body: Center(
            child: FlatButton(
              onPressed: () {
                vm.setTitle("State2");
              },
              child: Text(vm.text),
            ),
          ),
        ),
      ),
    );
  }
}