#flutter #dart
#flutter #dart
Вопрос:
Ниже приведен макет кода для универсального StatefulWidget, который использует FutureBuilder. Я получаю следующую ошибку при создании экземпляра FutureBuilder:
type '(User) => Future<List<User>>' is not a subtype of type '(dynamic) => Future<List<dynamic>>'
Я подозреваю, что ошибка заключается в том, что компилятор не будет знать об этом T
, и U
они одинаковы, поэтому U
объявляются как динамические, а T
как User
? Как бы мне изменить этот код, чтобы тип, используемый для общего в StatefulWidget, передавался в виджет состояния?
Widget build(BuildContext context) => TestWidget<User>();
class TestWidget<T> extends StatefulWidget {
final Future<List<T>> Function(T) myFunc = (_) => Future<List<T>>(null);
@override
_TestState<T> createState() => _TestState<T>();
}
class _TestState<U> extends State<TestWidget> {
@override
Widget build(BuildContext context) {
return FutureBuilder<List<U>>(
future: widget.myFunc(null),
builder: (context, snapshot) {
return Container();
});
}
}
Комментарии:
1. Вы можете легко проверить, что U совпадает с T. На самом деле, вам даже не нужно изменять возвращаемый тип состояния создания:
State createState() => _TestState<T>();
2. Проблема в вашем объявлении myFunc. Вероятно, вам потребуется создать именованное будущее для выполнения какой-либо работы.
3. Я совершенно не понимаю, как это вообще скомпилировано, учитывая, что вы передаете null в качестве вычисления Future
4.
Future<List<T>> myFunc(_) async { return []; }
было бы рабочим объявлением5. Спасибо @AlexeySubbotin. Да, будущее бесполезно, но оно скомпилировано и запущено. Я больше пытался показать свою борьбу с дженериками. Мое фактическое будущее работает нормально.
Ответ №1:
Для тех, кто ищет решение, вы можете увидеть, как FutureBuilder решил эту проблему. Вместо того чтобы писать возвращаемый тип _TestState<T>
для createState()
метода, вы бы написали State<TestWidget<T>>
.
State<TestWidget<T>> createState() => _TestState <T>();
Ответ №2:
В итоге я эффективно создал вторую build()
функцию в классе StatefulWidget, которая использует T
общий. Он вызывается из build()
класса состояния. Таким образом, класс состояния не заботится о дженериках. Я бы переключился на StatelessWidget с управляемыми состояниями, но мне нужно использовать AutomaticKeepAliveClientMixin, поэтому пришлось придерживаться StatefulWidget. Мой фактический класс состояния использует mixin и имеет немного больше возможностей.
class TestWidget<T> extends StatefulWidget {
final Future<List<T>> Function(T) myFunc = (_) => Future<List<T>>(null);
Widget build(BuildContext context) {
return FutureBuilder<List<T>>(
future: myFunc(null),
builder: (context, snapshot) {
return Container();
});
}
@override
_TestState createState() => _TestState();
}
class _TestState extends State<TestWidget> {
@override
Widget build(BuildContext context) {
return widget.build(context);
}
}