title: Flutter: Display content from paginated API with dynamic ListView
body: <p>I am new to Flutter so please bear with me. I have a paginated API that means on calling <code>example.com?loaditems.php?page=0</code> will load first 10 items(podcasts list) and <code>example.com?loaditems.php?page=1</code> will load items from 10 to 20 and so on.
  I want StreamBuilder to fetch page 0 first then when the list reaches the bottom it should load page 1 and show it. To check if I have reached the last item in listview I am using <code>ScrollController</code> of ListView.</p>
  
  <p>Now I am using StreamBuilder, ListView, InheritedWidget in bloc pattern. I am not sure if I have implemented it correctly so I am gonna paste the entire code.
  My question is, is this is the correct BLOC pattern way to do it? If not then what is it?
  I also came across with this article: <a href="https://crossingthestreams.io/loading-paginated-data-with-list-views-in-flutter/" rel="noreferrer">https://crossingthestreams.io/loading-paginated-data-with-list-views-in-flutter/</a>
  In the end it says "Update:" but I could not understand it much.</p>
  
  <p>Here' the <strong>app's entry point</strong>:</p>
  
  <pre><code>void main() =&gt; runApp(new MaterialApp(
  title: "XYZ",
  theme: ThemeData(fontFamily: 'Lato'),
  home: PodcastsProvider( //This is InheritedWidget
    child: RecentPodcasts(), //This is the child of InheritedWidget
   ),
  ));
  </code></pre>
  
  <p>Here's the <strong>InheritedWidget PodcastsProvider:</strong></p>
  
  <pre><code>class PodcastsProvider extends InheritedWidget{
  
      final PodcastsBloc bloc;  //THIS IS THE BLOC
  
      PodcastsProvider({Key key, Widget child})
      :   bloc = PodcastsBloc(),
      super(key: key, child: child);
  
      @override
      bool updateShouldNotify(InheritedWidget oldWidget) {
        return true;
      }
  
      static PodcastsBloc of(BuildContext context){
        return (context.inheritFromWidgetOfExactType(PodcastsProvider) as 
  PodcastsProvider).bloc;
      }
  }
  </code></pre>
  
  <p>Here's the <strong>Bloc</strong></p>
  
  <pre><code>class PodcastsBloc{
  
      var _podcasts = PublishSubject&lt;List&lt;Podcast&gt;&gt;();
  
      Observable&lt;List&lt;Podcast&gt;&gt; get podcasts =&gt;_podcasts.stream;
  
      getPodcasts(pageCount) async{
        NetworkProvider provider = NetworkProvider();
        var podcasts = await provider.getRecentPodcasts(pageCount);
       _podcasts.sink.add(podcasts);
      }
  
      despose(){
        _podcasts.close();
      }
  }
  </code></pre>
  
  <p>Here's the <strong>view part (child of InheritedWidget)</strong></p>
  
  <pre><code>class RecentPodcasts extends StatefulWidget {
     @override
    _RecentPodcastsState createState() =&gt; _RecentPodcastsState();
  }
  
  class _RecentPodcastsState extends State&lt;RecentPodcasts&gt; {
     ScrollController controller = ScrollController();
     PodcastsBloc podcastsBloc;
     bool isLoading = false;
     List&lt;Podcast&gt; podcasts;
  
     @override
     void didChangeDependencies() {
       super.didChangeDependencies();
       podcastsBloc = PodcastsProvider.of(context);
       podcastsBloc.getPodcasts(null);
       controller.addListener((){
       if(controller.position.pixels == controller.position.maxScrollExtent &amp;&amp; !isLoading){
         setState(() {
           isLoading = true;
           podcastsBloc.getPodcasts(podcasts[podcasts.length-1].id);
         });
        }
       }); //listerner ends
     }
  </code></pre>
  
  <p>Finally, <strong>build method of _RecentPodcastsState</strong> calls this:</p>
  
  <pre><code>Widget getRecentPodcastsList(PodcastsBloc podcastsBloc) {
  
  return StreamBuilder(
    stream: podcastsBloc.podcasts,
    builder: (context, snapshot) {
      //isLoading = false;
      if (snapshot.hasData) {
  
        podcasts.addAll(snapshot.data); //THIS IS A PROBLEM, THIS GIVES ME AN ERROR: flutter: Tried calling: addAll(Instance(length:20) of '_GrowableList')
  
        return ListView.builder(
            scrollDirection: Axis.vertical,
            padding: EdgeInsets.zero,
            controller: controller,
            itemCount: podcasts.length,
            itemBuilder: (context, index) {
              return RecentPodcastListItem(podcasts[index]);
            });
      } else if (snapshot.hasError) {
        //SHOW ERROR TEXT
        return Text("Error!");
      } else {
        //LOADER GOES HERE
        return Text(
          "Loading...",
          style: TextStyle(color: Colors.white),
        );
      }
    },
  );
  }}
  </code></pre>