Home > front end >  How to refresh data periodically with Stream?
How to refresh data periodically with Stream?

Time:05-09

I have a Future function that accepts currencies. This function is in a separate file. On the main page, I accept it through the Future builder and expand the data. How can I update them dynamically with Stream? I need to update this data every 5 seconds. My Future func:

//fetch data from API
  Future<List<CurrencyModel>?> _fetchCurrency() async {
    currencyList = [];
    final response = await http.get(
      Uri.parse(
          'https:...'),
    );
    if (response.statusCode == 200) {
      List<dynamic> values = [];
      values = json.decode(response.body);
      if (values.isNotEmpty) {
        for (int i = 0; i < values.length; i  ) {
          if (values[i] != null) {
            Map<String, dynamic> map = values[i];
            currencyList.add(
              CurrencyModel.fromJson(map),
            );
          }
        }
      }
      return currencyList;
    } else {
      throw Exception('Failed to load currencies');
    }
  }

My body:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Currencies'),
        centerTitle: true,
      ),
      body: FutureBuilder(
        future: client.fetchCurrency(),
        builder: (BuildContext context,
            AsyncSnapshot<List<CurrencyModel>?> snapshot) {
          if (snapshot.hasData) {
            return ListView.builder(
              itemCount: currencyList.length,
              itemBuilder: (context, index) => CurrencyCard(
                currencyList[index],
              ),
            );
          } else if (snapshot.hasError) {
            return Text(
              '${snapshot.error}',
            );
          }
          return const Center(
            child: CircularProgressIndicator(),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: startTimer,
        child: const Icon(Icons.update_sharp),
      ),
    );
  }

CodePudding user response:

Use streamBuilder with stream

StreamController<List<CurrencyModel>> controller = StreamController<List<CurrencyModel>();

Timer? timer;

@override
void initState() {
  super.initState();
  timer = Timer.periodic(Duration(seconds: 5), (Timer t) => fetchCurrency());
}

void fetchCurrency(){
  //do your api call and add data to stream
 currencyList = [];
 final response = await http.get(
  Uri.parse(
      'https:...'),
 );
 if (response.statusCode == 200) {
  List<dynamic> values = [];
  values = json.decode(response.body);
  if (values.isNotEmpty) {
    for (int i = 0; i < values.length; i  ) {
      if (values[i] != null) {
        Map<String, dynamic> map = values[i];
        currencyList.add(
          CurrencyModel.fromJson(map),
        );
      }
    }
  }
  controller.add(currencyList); 
 } else {
   throw Exception('Failed to load currencies');
 }
}

@override
void dispose() {
  timer?.cancel();
  super.dispose();
}

// here is your stream builder
StreamBuilder<List<CurrencyModel>>(
  stream: controller.stream,
  builder: (
      context,
      AsyncSnapshot<List<CurrencyModel>> snapshot,
      ) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return CircularProgressIndicator();
    } else if (snapshot.connectionState == ConnectionState.active
        || snapshot.connectionState == ConnectionState.done) {
      if (snapshot.hasError) {
        return const Text('Error');
      } else if (snapshot.hasData) {
        // return your listview here
        return ListView.builder(
          itemCount: snapshot.data.length,
          itemBuilder: (context, index) => CurrencyCard(
            snapshot.data[index],
          ),
        );
       
      } else {
        return const Text('Empty data');
      }
    } else {
      return Text('State: ${snapshot.connectionState}');
    }
  },
),

CodePudding user response:

Here's a simple example of how to use a Stream and a StreamBuilderwhilepolling` data from an API:

class Issue72171944 extends StatefulWidget {
  const Issue72171944({Key? key}) : super(key: key);

  @override
  State<Issue72171944> createState() => _Issue72171944State();
}

class _Issue72171944State extends State<Issue72171944> {
  Uri url = Uri.parse('https://catfact.ninja/fact');

  final StreamController<String> _streamController = StreamController<String>();
  late Stream stream;

  @override
  void initState() {
    super.initState();
    stream = _streamController.stream;

    startPolling();
  }

  void startPolling(){
    Timer.periodic(const Duration(seconds: 5), (timer){
      http.get(url).then((response){
        if (response.statusCode == 200) {
          String catFact = jsonDecode(response.body)['fact'];
          _streamController.add(catFact);
        }
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: stream,
      builder: (context, snapshot){
        if(snapshot.hasData){
          return Padding(
            padding: const EdgeInsets.all(20.0),
            child: Text(snapshot.data.toString(),
              softWrap: true,
              maxLines: 3,
              overflow: TextOverflow.ellipsis,
            ),
          );
        } else{
          return const Text('No data');
        }
      },
    );
  }
}
  • Related