Skip to content

Instantly share code, notes, and snippets.

@georgesboris
Last active July 1, 2020 21:05
Show Gist options
  • Save georgesboris/55dab934def5d9db0c8bc11d012200f9 to your computer and use it in GitHub Desktop.
Save georgesboris/55dab934def5d9db0c8bc11d012200f9 to your computer and use it in GitHub Desktop.
Youse Dart DOJO - 2020 07 01 - Async Flutter Programming
//
// # Async Flutter Programming
//
// 1. Let's use our API class to fetch our users and list them.
// 2. Where should we trigger these requests?
// 3. Where should we store this state?
//
// 4. Extra: Let's pretend "UserAvatar" is quite an expensive widget.
// How would we refactor our code to make sure we don't re-build all "UserAvatar"s everytime
// one of the user score changes?
//
import 'package:flutter/material.dart';
// ==========================================================
// ALL WORK SHOULD BE DONE BELOW
// ==========================================================
class UserAvatar extends StatelessWidget {
final User user;
UserAvatar({
this.user
});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(16),
child: Column(
children: [
Text(
user.name,
style: Theme.of(context).textTheme.headline6,
),
SizedBox(height: 12),
Text(
"Score: ${user.score}",
style: Theme.of(context).textTheme.bodyText1,
),
]
),
);
}
}
class App extends StatefulWidget {
@override
_AppState createState() => _AppState();
}
class _AppState extends State<App> {
List<User> users = [];
void fetchUsers() async {
final userIds = await API.fetchUsers();
final usersList = await Future.wait(userIds.map((id) async {
return await API.fetchUser(id);
}));
setState(() {
users = usersList;
});
}
Future<List<User>> fetchUsers2() async {
final userIds = await API.fetchUsers();
return await Future.wait(userIds.map((id) async {
return await API.fetchUser(id);
}));
}
@override
initState() {
fetchUsers();
super.initState();
}
@override
Widget build(BuildContext context) {
return FutureBuilder<List<User>>(
future: fetchUsers2(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('Error');
}
if (!snapshot.hasData) {
return Text('Loading...');
}
final users = snapshot.data;
return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return UserAvatar(
user: User(
id: users[index].id,
name: users[index].name,
score: users[index].score
)
);
}
);
}
);
/*if (users.length == 0) {
return Text("Loading...");
}
return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return UserAvatar(
user: User(
id: users[index].id,
name: users[index].name,
score: users[index].score
)
);
}
);*/
}
}
// ==========================================================
// ALL WORK SHOULD BE DONE ABOVE
// ==========================================================
class User {
final int id;
final String name;
final int score;
User({
@required this.id,
@required this.name,
@required this.score,
});
}
class API {
static Map<int, User> _users = {
0: User(id: 0, name: "David Bowie", score: 400),
1: User(id: 1, name: "Philip Glass", score: 100),
2: User(id: 2, name: "Kendrick Lamar", score: 200),
3: User(id: 3, name: "Marco Marques", score: 300),
4: User(id: 4, name: "David Lynch", score: 600),
};
static Future<List<int>> fetchUsers() {
return Future.delayed(Duration(milliseconds: 400), () => [
0, 1, 2, 3, 4
]);
}
static Future<User> fetchUser(int userId) {
return Future.delayed(Duration(milliseconds: 500), () => _users[userId]);
}
}
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: App(),
),
);
}
}
void main() {
runApp(MyApp());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment