Reputation: 152
I'm trying to animate a container in a FutureBuilder widget which makes a request to a node js api on localhost. There seems to have no issues with the API, but I've noticed that the Container renders normally when I don't call controller.repeat()
. i'm guessing that controller.repeat()
doesn't work well asynchronously, but I haven't found any alternatives.
This is the code I've got so far:
class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
AnimationController controller;
Animation<double> animation;
void initState() {
super.initState();
controller = AnimationController(
duration: const Duration(milliseconds: 3000), vsync: this);
animation = Tween<double>(begin: 10, end: 300).animate(controller);
animation.addListener(() {
setState(() {});
});
}
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final url = Uri.parse("http://localhost:8080");
return FutureBuilder(
future: http.get(url),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
final themeList =
Map<String, dynamic>.from(jsonDecode(snapshot.data.body));
final keys = List.from(themeList.keys);
controller.repeat(); // Container shows when I comment this line out
return Center(
child: Container(
color: Colors.red,
width: animation.value,
height: animation.value,
),
);
} else {
return Center(child: CircularProgressIndicator());
}
});
}
}
Upvotes: 2
Views: 873
Reputation: 2490
Please separate your animated widget. In your code, every setState(...)
call will re-request the http.get(...)
.
Do something like this...
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: const Scaffold(
body: Center(
child: Home(),
),
),
);
}
}
class Home extends StatelessWidget {
const Home();
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: Future<void>.delayed(const Duration(seconds: 2), () {}),
builder: (context, snapshot) =>
snapshot.connectionState == ConnectionState.done
? const Center(child: AnimatedContainer())
: const Center(child: CircularProgressIndicator()),
);
}
}
class AnimatedContainer extends StatefulWidget {
const AnimatedContainer();
@override
_AnimatedContainer createState() => _AnimatedContainer();
}
class _AnimatedContainer extends State<AnimatedContainer>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 3000),
vsync: this,
);
_animation = Tween<double>(begin: 10, end: 300).animate(_controller);
_animation.addListener(() {
setState(() {});
});
// _controller.repeat();
_controller.forward();
}
@override
Widget build(BuildContext context) {
return Container(
color: Colors.red,
width: _animation.value,
height: _animation.value,
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
Upvotes: 1