I'm trying to create a generic consumer widget that facilitates the ViewModel to its child. therefor I have two functions. one that has a function(T) after init of the ViewModel and the other for passing the model to its child Widget.
in the generic class is a child of ChangeNotifier and that works fine until I want to send the T value in the two Functions.
then I get the following errors:
type '(OnBoardingViewModel) => Null' is not a subtype of type
'(ChangeNotifier) => void'
and
type '(BuildContext, OnBoardingViewModel, Widget) => Scaffold' is not
a subtype of type
'(BuildContext, ChangeNotifier, Widget) => Widget'
But when i change the extends type from ChangeNotifier to OnBoardingViewModel, everything works fine.
can someone help me and or explain why this ain't working??
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:provider/provider.dart';
class StateFullConsumerWidget 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 createState() => _StateFullConsumerWidgetState();
}
class _StateFullConsumerWidgetState extends State{
T _viewModel;
@override
void initState() {
// assign the model once when state is initialised
_viewModel = GetIt.instance.get();
widget.onPostViewModelInit(_viewModel);
super.initState();
}
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
builder: (context) => _viewModel,
child: Consumer(
builder: widget.builder,
child: widget.child,
),
);
}
}
my widget
StateFullConsumerWidget(
onPostViewModelInit: (viewModel){
buildIntroList(viewModel);
viewModel.maxPages = _introWidgetsList.length;
},
builder: (context,viewModel,child) {
return Scaffold(
key: widget.scaffoldKey,
body: SafeArea(
child: Container(),
),
),
);
},
);
my ViewModel
import 'package:flutter/material.dart';
class OnBoardingViewModel extends ChangeNotifier{
OnBoardingViewModel(){
}
}
解决方案
The way you are using the generic type T is incomplete. The relationship between the StateFullConsumerWidget and the _StateFullConsumerWidgetState classes as written in your code are such that StateFullConsumerWidget creates its state using the same T type parameter as itself, so the widget knows the state uses the same generic type that it does. From the perspective of _StateFullConsumerWidgetState, though, the class is declared as such:
class _StateFullConsumerWidgetState
extends State
The problem is the state class is using the general form of StateFullConsumerWidget, so there is no explicit relationship between the T that _StateFullConsumerWidgetState is receiving as the type parameter and the T that StateFullConsumerWidget is using. Dart doesn't know how to reconcile this ambiguous relationship, so it defaults to the lowest common denominator the type constraints allow, which is ChangeNotifier.
Because of this, when you try to treat T as OnBoardingViewModel, Dart throws an error because, as far as the state class knows, the T of the parent widget is ChangeNotifier, not OnBoardingViewModel.
You can fix this by passing the type parameter along when you declare your state class:
class _StateFullConsumerWidgetState
extends State>