Example of build a widget using Future.map() #26
-
Hi guys, can you share an example of a Flutter page that shows a circular progress indicator, the result or the error when calling a future, please? I'm trying something like:
And trying build a widget like this but it's not working...
|
Beta Was this translation helpful? Give feedback.
Replies: 8 comments 15 replies
-
Here is an example using the new final counterFutureSignal = futureSignal(counterFuture);
Future<String> counterFuture() async {
print('counterFuture');
await Future.delayed(const Duration(seconds: 1));
return 'One second has passed.';
}
...
@override
Widget build(BuildContext context) {
return Watch((context) {
return counterFutureSignal.map(
value: (value) => Text(
value,
style: Theme.of(context).textTheme.headlineMedium!,
),
error: (error) => Text(
'error:$error',
style: Theme.of(context).textTheme.headlineMedium!,
),
loading: () => const CircularProgressIndicator(),
);
});
} |
Beta Was this translation helpful? Give feedback.
-
Hi, Rody, thanks for the answer, I experimented with the code below but it triggers the loading only (no more loading when I press the random button) once and when it 'randomly' throws an exception it crashes with 'Unhandled Exception: Exception: Exception'.
|
Beta Was this translation helpful? Give feedback.
-
Fixed on version 1.3.1: import 'dart:math';
import 'package:flutter/material.dart';
import 'package:signals/signals_flutter.dart';
Future<int?> myFuture() async {
print('myFuture');
await Future.delayed(const Duration(milliseconds: 1000));
int number = Random().nextInt(10);
if (number.isEven) {
return number;
} else {
throw Exception('Exception');
}
}
final myFutureSignal = futureSignal(() => myFuture());
final counter = signal(0);
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
void _random() async {
counter.value++;
myFutureSignal.reset();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'${counter.watch(context)}',
style: Theme.of(context).textTheme.headlineMedium,
),
Watch((context) {
return myFutureSignal.map(value: (value) {
print('value:$value');
return Text(
value.toString(),
style: Theme.of(context).textTheme.headlineMedium!,
);
}, error: (error) {
print('error:$error');
return Text(
'error:$error',
style: Theme.of(context).textTheme.headlineMedium!,
);
}, loading: () {
print('loading');
return const CircularProgressIndicator();
});
}),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _random,
tooltip: 'Random',
child: const Icon(Icons.refresh),
),
);
}
} This was a good example and used it to test out some stuff. There was some exception and state not getting propagated. Also It now extends |
Beta Was this translation helpful? Give feedback.
-
Since |
Beta Was this translation helpful? Give feedback.
-
@rivella50 Right now, you have to manually watch the |
Beta Was this translation helpful? Give feedback.
-
@rodydavis Hi Mr. Rody, any chance to update my example to the new AsyncSignal, please? The way I did it call an asyncsignal every time I enter the page (but it must call only when I press the button) and I can handle the loading state with a boolean signal but I'm not getting to show an text error widget with some hasError boolean signal... |
Beta Was this translation helpful? Give feedback.
-
Example using AsyncSignal: import 'dart:math';
import 'package:flutter/material.dart';
import 'package:signals/signals_flutter.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const Example(),
);
}
}
class Example extends StatefulWidget {
const Example({super.key, required this.title});
final String title;
@override
State<Example> createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
final throwError = signal(false);
final delay = signal(500);
late final _futureSignal = futureSignal(() => _future());
Future<int> _future() async {
await Future.delayed(Duration(milliseconds: delay.value));
if (throwError.value) {
throw Exception('Error');
} else {
return Random().nextInt(1000);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Watch((_) {
return SwitchListTile(
title: const Text('Throw Error'),
value: throwError.value,
onChanged: (value) => throwError.value = value,
);
}),
Watch((context) {
return ListTile(
title: const Text('Result'),
subtitle: _futureSignal.value.map(
data: (value) {
return Text(
value.toString(),
style: Theme.of(context).textTheme.headlineMedium!,
);
},
error: (error, _) {
return Text(
'error:$error',
style: Theme.of(context).textTheme.headlineMedium!,
);
},
loading: () {
return const Center(child: CircularProgressIndicator());
},
reloading: () {
return Text(
'reloading',
style: Theme.of(context).textTheme.headlineMedium!,
);
},
refreshing: () {
return Text(
'refreshing',
style: Theme.of(context).textTheme.headlineMedium!,
);
},
),
);
}),
Row(
children: [
Flexible(
child: ElevatedButton(
child: const Text('Reload'),
onPressed: () => _futureSignal.reload(),
),
),
const SizedBox(width: 10),
Flexible(
child: ElevatedButton(
child: const Text('Refresh'),
onPressed: () => _futureSignal.refresh(),
),
),
],
),
],
),
),
),
);
}
} |
Beta Was this translation helpful? Give feedback.
-
This is getting reworked on this PR, but I think the API will work a lot better: |
Beta Was this translation helpful? Give feedback.
Example using AsyncSignal: