I always do the same thing with a FutureBuilder in my flutter app, so I want to get rid of the duplicated code and provide a widget for that.
I have an abstract interface class Service
and my widget uses the generic types <T extends Object, S extends Service>
. The class AuthenticationService
implements my Service
interface.
My widget looks like this:
class NewStandardFutureBuilder<T extends Object, S extends Service>
extends StatefulWidget {
const NewStandardFutureBuilder({
super.key,
required this.service,
required this.createFuture,
required this.builder,
});
final S service;
final Future<T> Function(S) createFuture;
final DataWidgetBuilder<T> builder;
@override
State<NewStandardFutureBuilder> createState() =>
_NewStandardFutureBuilderState<T, S>();
}
class _NewStandardFutureBuilderState<T extends Object, S extends Service>
extends State<NewStandardFutureBuilder> {
late Future<T> future;
@override
void initState() {
super.initState();
future = widget.createFuture(widget.service) as Future<T>;
}
Future<void> load() async {
setState(() {
future = widget.createFuture(widget.service as S) as Future<T>;
});
}
@override
Widget build(BuildContext context) {
return FutureBuilder<T>(
future: future,
builder: (context, snapshot) {...},
);
}
}
I try to use the widget like this:
return NewStandardFutureBuilder<String, AuthenticationService>(
service: AuthenticationService(),
createFuture: (service) => service.getUsername(),
builder: (username) => Text('You are logged in as $username'),
);
The class AuthenticationService implements the Service interface. I get the error in the initState
-method:
type '(AuthenticationService) => Future<String>' is not a subtype of type '(Service) => Future<Object>'
How do I fix this problem?
Thanks!
2
Answers
From, the documentation on substituting types:
Here, the parameter of the function is a consumer, so you can substitute it with a supertype, but not subtype.
You can see the example on the methods section. Passing callback function is a similar case to overriding method, as shown in the example.
For the solution, you might want to write your code in algebraic data types. It shows an example of having a single method that covers two different types under the same supertype like this:
You forgot to make sure your state gets a properly typed widget:
It needs to include
<T, S>
:Then you will get about 3 errors of "unneccessary cast", so just remove those, they are indeed unneccessary.