1

after whole day of trying to solve this myself I had to come and ask for help.

I'm trying to build this ListView.builder, it has fixed amount of itemCount. And its building Widgets using data retrieved from locally stored JSON file.

I'm using Provider to pass that data around. The problem is, on app start or hot restart that ListView.builder turns red and shows error, and then after like quarter of a second it shows my data.

I understand why this happens, my list of data that I get from json is initially empty. So I put ternary operator like: provider.data == null ? CircularProgressIndicator() : ListView.builder... but this doesnt stop it from crashing.

I dont know why and its driving me crazy. Here is full code:

We are talking here about widget called RecommendedCardList, its showing widgets from above mentioned list by having random number (in range of list length) as index.

I have similar ListView on HomeScreen called CategoryCardList and its working similarly to RecommendedCardList but I'm not having this issue with it. Also the rest of the home screen shows good, only the portion where RecommendedCardList is turns red for a short period of time.

Home Screen class:

    class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Get user's screen properties
    // We are using this properties to adjust size accordingly
    // In order to achieve maximum responsivnes for different screen sizes
    var height = MediaQuery.of(context).size.height;
    var width = MediaQuery.of(context).size.width;

    var repoProvider = Provider.of<Repository>(context);
    var recipeDataList = repoProvider.recipeDataList;

    return Container(
      color: backgroundColor,
      child: repoProvider.recipeDataList == null
          ? Center(child: CircularProgressIndicator())
          : Padding(
              padding: contentPadding,
              child: ListView(
                children: <Widget>[
                  AppTitle(),
                  SizedBox(
                    height: height * 0.03,
                  ),
                  Column(
                    children: <Widget>[
                      CategoryAndSeeAll(),
                      CategoryCardsList(height: height, provider: repoProvider),
                    ],
                  ),
                  SizedBox(
                    height: height * 0.05,
                  ),
                  Container(
                    width: double.infinity,
                    height: height * 0.1,
                    decoration: BoxDecoration(
                      border: Border.all(color: accentColor),
                    ),
                    child: Text(
                      'Reserved for AD',
                      textAlign: TextAlign.center,
                    ),
                  ),
                  SizedBox(
                    height: height * 0.05,
                  ),
                RecommendedCardsList(height: height, width: width, recipeDataList: recipeDataList),
                ],
              ),
            ),
    );
     }



       }

RecommendedCardsList class:

class RecommendedCardsList extends StatelessWidget {
  const RecommendedCardsList({
    Key key,
    @required this.height,
    @required this.width,
    @required this.recipeDataList,
  }) : super(key: key);

  final double height;
  final double width;
  final recipeDataList;
  @override
  Widget build(BuildContext context) {

    return Container(
            height: height * 0.30,
            child: ListView.builder(
                scrollDirection: Axis.horizontal,
                itemCount: numberOfRecommendedRecipes,
                itemBuilder: (context, counter) {
                  int randomNumber = Random().nextInt(recipeDataList.length);
                  return Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                     RecommendedCard(
                        width: width,
                        height: height,
                        imagePath: recipeDataList.elementAt(randomNumber).image,
                        text: recipeDataList.elementAt(randomNumber).title,
                      ),
                    ],
                  );

                }),





          );
  }
}

Repository class:

class Repository extends ChangeNotifier {
  Repository() {
    loadJson();
  }

  var _recipeData;


  List<RecipeModel> _recipeDataList = [];
  List<RecipeModel> get recipeDataList => _recipeDataList;

  void loadJson() async {

    var json = await rootBundle.loadString('assets/recipes.json');
    var parsedJson = jsonDecode(json);
    for (var item in parsedJson) {
      _recipeData = RecipeModel.fromJson(item);
      _recipeDataList.add(_recipeData);
    }
    //print('Title:${_recipeDataList[0].title}\nImage:${_recipeDataList[0].image}'); // For debugging

    notifyListeners();
  }
}
7
  • where does this variable (numberOfRecommendedRecipes on second bloc code) come from? Commented Jun 3, 2020 at 21:14
  • Are you notifying the change and rebuilding the HomeScreen? You can wrap with FutureProvider Commented Jun 3, 2020 at 21:16
  • @RocignoMedeiros thats just an integer value from my 'values.dart' file.. I store some simple values dare. Its basically set to 6. As I want only 6 of these widgets. Commented Jun 3, 2020 at 21:22
  • @SanjaySharma of course I'm calling notifyListeners, nothing would update if I didnt. Like I said, my stuff shows up, but that particular List builder is throwing error for a moment :( confusing af. Commented Jun 3, 2020 at 21:22
  • The actual error is : RangeError (max): Must be positive and <= 2^32: Not in range 1..4294967296, inclusive: 0 /// The one in title is cause I thought its somehow Random int that causes this, so I removed it, set fixed index of 1 and got the same but a bit different error message. Commented Jun 3, 2020 at 21:24

2 Answers 2

1

This error is related to the fact that the code searched for an index in your list and this index is more than you list length.

I think the error is in that part:

int randomNumber = Random().nextInt(recipeDataList.length);

Supposing the length is 10 the random function will retrieve a num between 0 and 10, but the last index is 9.

With that in mind, I have two suggestions:

1)

// changing ternary logic
(repoProvider.recipeDataList == null && repoProvider.recipeDataList.length > 0)

2)

// inside ListView.Builder change to get the list length
itemCount: recipeDataList.length
Sign up to request clarification or add additional context in comments.

2 Comments

1. doesnt work, same error happens. I tried it in both HomeScreen and RecommendedCardsList.. 2. This list is 50 items long, I dont need that many widgets, thats why I set different value on itemCount... Its not Random.NextInt related since I tried without it and its still the same :D
Actually that 1. worked as it is. I had to negate it only cause of my widget position. Good job.
1

Put the following condition in build() of RecommendedCardsList widget as the first line.

if(recipeDataList == null || recipeDataList.length == 0){
  return Container();
}

6 Comments

No difference since I set recipeDataList = repoProvider.recipeDataList ... It's in the code :)
Can you confirm if the value of numberOfRecommendedRecipes is greater than the list size?
I added it to first post.... I have like 40-50 items in that list, its not greater :)
This fixes it! Thanks bro, drinks on me
You could have also change this condition in HomeScreen to fix this repoProvider.recipeDataList == null with repoProvider.recipeDataList == null && repoProvider.recipeDataList.length !=0
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.