Last active
May 10, 2024 17:05
-
-
Save hectorAguero/c71c5a088421479e1525e450353f7e28 to your computer and use it in GitHub Desktop.
AsyncValue with ValueNotifier
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/foundation.dart'; | |
import 'package:flutter/material.dart'; | |
void main() => runApp(const MyApp()); | |
class MyApp extends StatelessWidget { | |
const MyApp({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return const MaterialApp( | |
home: HomePage(), | |
); | |
} | |
} | |
class HomePage extends StatefulWidget { | |
const HomePage({super.key}); | |
@override | |
State<HomePage> createState() => _HomePageState(); | |
} | |
typedef AsyncValueNotifier<T> = ValueNotifier<AsyncValue<T>>; | |
class _HomePageState extends State<HomePage> { | |
final AsyncValueNotifier<User> userNotifier = ValueNotifier(AsyncLoading()); | |
@override | |
void initState() { | |
super.initState(); | |
simulateFetchUser(); | |
} | |
Future<void> simulateFetchUser() async { | |
try { | |
// Simulating network request | |
await Future.delayed(const Duration(seconds: 1)); | |
const user = User(name: 'John Doe', id: 1, phones: ['123-456-7890']); | |
userNotifier.value = AsyncData(user); | |
//throw Exception('Failed to fetch user'); | |
} catch (e) { | |
userNotifier.value = AsyncError(e as Exception); | |
} | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: const Text('Sealed Classes with Switch')), | |
body: Center( | |
child: ValueListenableBuilder<AsyncValue<User>>( | |
valueListenable: userNotifier, | |
builder: (_, value, __) => switch (value) { | |
AsyncData(:final data) => | |
Text('${data.name}\n${data.phones ?? 'No Phones'}'), | |
AsyncError(:final exception) => Text('$exception'), | |
AsyncLoading() => const CircularProgressIndicator(), | |
}, | |
), | |
), | |
floatingActionButton: UserFab(userNotifier: userNotifier), | |
); | |
} | |
} | |
class UserFab extends StatelessWidget { | |
const UserFab({required this.userNotifier, super.key}); | |
final AsyncValueNotifier<User> userNotifier; | |
@override | |
Widget build(BuildContext context) { | |
return FloatingActionButton.extended( | |
onPressed: () { | |
final user = userNotifier.value.dataOrNull; | |
if (user == null) return; | |
userNotifier.value = AsyncData( | |
user.copyWith(phones: user.phones == null ? ['987-654-3210'] : null), | |
); | |
}, | |
label: const Text('Change Phones'), | |
icon: const Icon(Icons.refresh), | |
); | |
} | |
} | |
sealed class AsyncValue<T> { | |
T? get dataOrNull => null; | |
} | |
class AsyncData<T> extends AsyncValue<T> { | |
final T data; | |
AsyncData(this.data); | |
@override | |
T get dataOrNull => data; | |
} | |
class AsyncError<T> extends AsyncValue<T> { | |
final Exception exception; | |
AsyncError(this.exception); | |
} | |
class AsyncLoading<T> extends AsyncValue<T> {} | |
// User immutable class | |
class User { | |
final String name; | |
final int id; | |
final List<String>? phones; | |
const User({required this.name, required this.id, this.phones}); | |
@override | |
String toString() { | |
return 'User{name: $name, id: $id, phones: $phones}'; | |
} | |
@override | |
bool operator ==(covariant User other) { | |
if (identical(this, other)) return true; | |
return other.name == name && | |
other.id == id && | |
listEquals(other.phones, phones); | |
} | |
@override | |
int get hashCode => name.hashCode ^ id.hashCode ^ phones.hashCode; | |
static const _unset = Object(); | |
User copyWith({ | |
String? name, | |
int? id, | |
Object? phones = _unset, // default to special marker | |
}) { | |
return User( | |
name: name ?? this.name, | |
id: id ?? this.id, | |
phones: phones == _unset ? this.phones : phones as List<String>?, | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment