I want to fetch data from coin gecko with its api. Using FutureProvider
to do this. FutureProvider only fetches the data once. So the data comes and UI builds successfully.However, I want to listen all changes on each cryptocurrency, and rebuild the widget. I am using riverpod's FutureProvider. If I was able to send request to service, and fetch data every 15 seconds, and rebuild the UI, this would solve my problem. But i couldn't do it. Moreover, I want to learn what is the most efficient way to do this am I following the right path?
Any help appreciated. :)
final marketProvider = FutureProvider<List<Coin>>(
(ref) async => await DataService().fetch_coin_data(),
);
class CoinListPage extends ConsumerWidget {
const CoinListPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
AsyncValue<List<Coin>> coinList = ref.watch(marketProvider);
return Scaffold(
appBar: AppBar(
title: const Text("T I T L E"),
),
body: Center(
child: coinList.when(
data: (data) => CoinList(coinList: data),
error: (e, stack) => Text('Error: $e'),
loading: () => const CircularProgressIndicator(),
),
),
);
}
}
Future<List<Coin>> fetch_coin_data() async {
List<Coin> _coinList = <Coin>[];
final resp = await http.get(Uri.parse(
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=10&page=1&sparkline=false&price_change_percentage=24h"));
if (resp.statusCode == 200) {
// If the call to the server was successful, parse the JSON
List<dynamic> decoded = json.decode(resp.body);
for (dynamic coin in decoded) {
_coinList.add(Coin.fromJson(coin));
}
return _coinList;
} else {
// If that call was not successful, throw an error.
throw Exception('Request Error!');
}
}
I couldn't figure out which provider should I use for this purpose. Any help appreciated!
CodePudding user response:
FutureProvider
is designed to solve simple use-cases.
For more advanced scenarios, consider using StateNotifierProvider
.
FutureProvider
returns an AsyncValue
, so we can create a StateNotifierProvider
with state type AsyncValue
, which will update fetch data and update state every 15 seconds.
final marketProvider = StateNotifierProvider<MarketNotifier, AsyncValue>((ref) {
return MarketNotifier();
});
class MarketNotifier extends StateNotifier<AsyncValue> {
MarketNotifier() : super(const AsyncValue.loading()) {
fetchLoopWithDelay(const Duration(seconds: 15));
}
Future<void> fetchLoopWithDelay(Duration delay) async {
while (true) {
try {
final data = await DataService().fetch_coin_data();
state = AsyncValue.data(data);
} catch (e) {
state = AsyncValue.error(e, StackTrace.current);
}
await Future.delayed(delay);
}
}
}