Chethan Venkataramaiah
Chethan Venkataramaiah

Reputation: 135

Why is my future builder still not working in spite of await in flutter?

I am working on a LiveTv app.Everytime I try to load the app using API's it says "RangeError (index): Invalid value: Valid value range is empty: 0 ". So I understood because at the time when I load the app the data is not loaded and therefore the error.

So I used something called as future builder.But inspite of that I am still getting the same error but after sometime it loads.I tried putting counters because it takes time for the for loop as well to be built but still the same error keeps happening.I just don't know where I am going wrong

Below is the code and below each snipped I have put I have included a brief description.Please have a look:

Widget build(BuildContext context) {
    Widget widgetOptions(int idx) {
      Widget _selectedWidget = CircularProgressIndicator();
      switch (idx) {
        case 0:
          _selectedWidget = homePageForBottomNavigator();
          break;
        case 1:
          _selectedWidget = MoviesPageForBottomNavigator();
          break;
        case 2:
          _selectedWidget = TvSHowsPageOfBottomNavigator();
          break;
        case 3:
          _selectedWidget = MusicPageofBottomNavigator();

          break;
        case 4:
          _selectedWidget = NewsPageOfBottomNavigator();

          break;
        case 5:
          _selectedWidget = LifeStylePageOfBottomNavigator();
          break;
        case 6:
          _selectedWidget = SportsPageOfBottomNavigator();
      }
      return _selectedWidget;
    }

    return Scaffold(
      //   key: _drawerKey,
         body: SafeArea(
        child: SingleChildScrollView(
            controller: _scrollController,
            child: FutureBuilder(
                future: widgetLoadingFunctions(_selectedIndex),
                builder: (BuildContext context, AsyncSnapshot snapshot) {
                  if (snapshot.hasData != null) {
                    return widgetOptions(_selectedIndex);
                  } else
                    return CircularProgressIndicator();
                })),
      ),
      drawer: Drawer(),
      bottomNavigationBar: BottomNavigationBar(
        backgroundColor: Colors.black,
        showUnselectedLabels: true,
        type: BottomNavigationBarType.shifting,
        currentIndex: _selectedIndex,
        fixedColor: Colors.amber,
        onTap: (int index) {
          setState(() {
            _selectedIndex = index;
          });
        },
        items: <BottomNavigationBarItem>[
//          Icon(
//            FontAwesome.facebook_square,
//            color: Colors.amber,
//          ),
          BottomNavigationBarItem(
            backgroundColor: Colors.black,
            icon: Icon(Icons.home),
            title: Text('Home'),
          ),
          BottomNavigationBarItem(
            backgroundColor: Colors.black,
            icon: Icon(
              MaterialCommunityIcons.video_vintage,
            ),
            title: Text(
              'Movies',
            ),
          ),
          BottomNavigationBarItem(
            backgroundColor: Colors.black,
            icon: Icon(Icons.live_tv),
            title: Text(
              'Tv shows',
            ),
          ),

          BottomNavigationBarItem(
            backgroundColor: Colors.black,
            icon: Icon(Icons.music_video),
            title: Text(
              'Music',
            ),
          ),
          BottomNavigationBarItem(
            backgroundColor: Colors.black,
            icon: Icon(Icons.radio),
            title: Text(
              'News',
            ),
          ),
          BottomNavigationBarItem(
            backgroundColor: Colors.black,
            icon: Icon(
              FontAwesome.heartbeat,
            ),
            title: Text(
              'LifeStyle',
            ),
          ),
          BottomNavigationBarItem(
            backgroundColor: Colors.black,
            icon: Icon(
              Ionicons.md_football,
            ),
            title: Text(
              'Sports',
            ),
          ),
        ],
      ),
    );
   }
}

So in the above code is there is the bottom navigation bar whose selected_index dictates which async function has to be loaded and then the corresponding widget has to be loaded .I will put in the async function below and the corresponding switch statement of the future as well.

Future widgetLoadingFunctions(int idx) async {
    var _selectedFunxtion;
    switch (idx) {
      case 0:
        _selectedFunxtion = await functionsToBeLoadedForHomePage();
        break;
      case 1:
        _selectedFunxtion = //yet to be implemented
        break;
      case 2:
        _selectedFunxtion =  //yet to be implemented
        break;
      case 3:
        _selectedFunxtion = //yet to be implemented

        break;
      case 4:
        _selectedFunxtion = //yet to be implemented

        break;
      case 5:
        _selectedFunxtion =  //yet to be implemented
        break;
      case 6:
        _selectedFunxtion = //yet to be implemented
    }
    return _selectedFunxtion;
  }

and this is the async function:

Future functionsToBeLoadedForHomePage() async {
    int counter = 10;
    String url =
        "https://livetvapi.apyhi.com/api/v3/home?pageLocation=home&countries=IN&app_version=13&"
        "user_id=44edc2c905ae163f&package_id=livetv.movies.freemovies.watchtv.tvshows&os_platform=android";

    var res = await http
        .get(url, headers: {'Authorization': dartJsonWebTokenGenerator()});

    if (res.statusCode == 200) {
      final _homePage = homePageFromJson(res.body);

      for (var homeBannerObject in _homePage.homeBanners) {
        setState(() {
          _homeBannerObjectMovieIdList.add(homeBannerObject.movieId);
          counter = counter - 1;
        });
      }

      for (var homeBannerObject in _homePage.movies) {
        setState(() {
          _popularMoviesMovieId.add(homeBannerObject.movieId);
          counter = counter - 1;
        });
      }

      for (var homeBannerObject in _homePage.series) {
        setState(() {
          _seriesData.add(homeBannerObject.posterLink);
          counter = counter - 1;
        });
      }

      for (var homeBannerObject in _homePage.musicCategories) {
        setState(() {
          _musicCategories.add(homeBannerObject.categoryName);
          counter = counter - 1;
        });
      }

      for (var playListObj in _homePage.musicPlaylists.playlists) {
        setState(() {
          _musicCategories.add(playListObj.playlistName);
          counter = counter - 1;
        });
      }

      for (var publisherObj in _homePage.publishers) {
        setState(() {
          _popularNewsChannelNames.add(publisherObj.fullName);
          counter = counter - 1;
        });
      }
      for (var publisherObj in _homePage.publishers) {
        setState(() {
          _popularNewsChannelProfilePicUrl.add(publisherObj.profilePicUrl);
          counter = counter - 1;
        });
      }
      for (var liveChannelObj in _homePage.liveChannels) {
        setState(() {
          _liveNewsChannelProfilePicUrl.add(liveChannelObj.publisherProfilePic);
          counter = counter - 1;
        });
      }
      for (var liveChannelObj in _homePage.liveChannels) {
        setState(() {
          _liveNewsChannelNames.add(liveChannelObj.publisherName);
          counter = counter - 1;
        });
      }
      setState(() {
        _musicPlaylistThemeName = _homePage.musicPlaylists.categoryName;
        counter = counter - 1;
        return counter == 0 ? "Successfully Exectued" : null;
      });
    } else
      return null;
// print("finished services...........................");
  }

I have put in the counter so that after all the lists have been loaded it turns 0 and a non-null value is returned

and the widget which will be eventually called is as follows:

  Widget homePageForBottomNavigator() {
    return Stack(
      children: <Widget>[
        Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            _buildBody(MediaQuery.of(context).size.height * 0.35,
                _homeBannerObjectMovieIdList),

            HorizontalListView("Popular movies", _popularMoviesMovieId, false),
            HorizontalListView("Popular Tv shows", _seriesData, false),
            //infinite list view to be implemented here
            HorizontalGridViewOfCardsofGradientColorWithtitle(1, "Music"),
//            HorizontalListViewWithoutViewAll(
//                _musicPlaylistThemeName , false),
            HorizontalListViewWitCircularCards("Popular News channels",
                _popularNewsChannelProfilePicUrl, _popularNewsChannelNames),
            HorizontalListViewWithoutViewAllForLiveNewsChannels(
                "Live News Channels",
                _liveNewsChannelProfilePicUrl,
                _liveNewsChannelNames),

            //VerticalListView(["Latest News"],false),
          ],
        ), //end of 1st Widget
        Positioned(
            bottom: MediaQuery.of(context).size.height * 0.01,
            left: MediaQuery.of(context).size.width * 0.3,
            child: returnToTopButton()),
      ],
    );
  }

The above 3 snippets have been written before the build function of the state object of the stateful widget

Upvotes: 0

Views: 887

Answers (1)

Develocode 777
Develocode 777

Reputation: 1305

In your FutureBuilder you have the condition wrong, (snapshot.hasData != null) is always true, it should be like this:

FutureBuilder(
                future: widgetLoadingFunctions(_selectedIndex),
                builder: (BuildContext context, AsyncSnapshot snapshot) {
                  if (snapshot.hasData) {
                    return widgetOptions(_selectedIndex);
                  } else
                    return CircularProgressIndicator();
                })),

or like this:

FutureBuilder(
                future: widgetLoadingFunctions(_selectedIndex),
                builder: (BuildContext context, AsyncSnapshot snapshot) {
                  if (snapshot.data != null) {
                    return widgetOptions(_selectedIndex);
                  } else
                    return CircularProgressIndicator();
                })),

Upvotes: 1

Related Questions