2021年2月9日星期二

Fetching multiple pages from an API and adding to stream sink

I'm fetching this API https://rickandmortyapi.com/api/character and putting the data inside a Stream so I can infinite scroll over a Gridview of Cards with every character. Fetching the first page with a FutureBuilder it works, but trying to use a StreamBuilder just doesn't update anything as if it wasn't receiving any data.

Here's the the Provider.dart

class CharacterProvider {    final _url = 'rickandmortyapi.com';    final _characterStream = StreamController<List<Character>>.broadcast();    List<Character> _characters = [];    int currentPage = 1;      Function(List<Character>) get characterSink => _characterStream.sink.add;    Stream<List<Character>> get characterStream => _characterStream.stream;      void dispose() {      _characterStream?.close();    }      Future<Map<String, dynamic>> fetchData(        String path, Map<String, dynamic> header) async {      print(header);      final response = await http.get(        Uri.https(_url, 'api/$path', header),      );        if (response.statusCode == 200) {        final results = jsonDecode(response.body);        return results;      } else {        throw Exception('Fallo al cargar personajes');      }    }      Future<List<Character>> fetchCharacters() async {      final path = 'character';      final header = {        'page': currentPage.toString(),      };      final data = await fetchData(path, header);      final characterFetched = Characters.fromJsonList(data['results']);      _characters.addAll(characterFetched.character);      characterSink(_characters);      if (currentPage < data['info']['pages']) {        currentPage++;      }      return characterFetched.character;    }  }    

The stream of StreamBuilder in the widget is subscribed to characterStream but it is always on null.

class _CharacterCardsState extends State<CharacterCards> {    final _scrollController = ScrollController();    Future<List<Character>> _characters;    int cards;    bool loading;      @override    void initState() {      super.initState();      print('Cards: init');      _characters = initFetch();      loading = true;      cards = 6;      _scrollController.addListener(updateCards);    }    Future<List<Character>> initFetch() async {      final fetch = await CharacterProvider().fetchCharacters();      return fetch;    }    @override    Widget build(BuildContext context) {      CharacterProvider().fetchCharacters();      print('Cards: build');      return GridView.builder(          itemCount: cards,          controller: _scrollController,          itemBuilder: (context, index) {            return StreamBuilder(              stream: CharacterProvider().characterStream,              builder: (BuildContext context,                  AsyncSnapshot<List<Character>> snapshot) {                if (snapshot.hasData) {                  loading = false;                  final character = snapshot.data;                  return GestureDetector(                    onTap: () {                      cardView(context, character, index);                    },                    child: ofCard(character, index),                  );                } else {                  return ofLoading(widget.size);                }              },            );          });    }  

On debug, the values added to the sink are non-null. The data is fetching correctly but the sink.add() doesn't seem to be working.

https://stackoverflow.com/questions/66131074/fetching-multiple-pages-from-an-api-and-adding-to-stream-sink February 10, 2021 at 12:51PM

没有评论:

发表评论