Почему функция возвращает пустой список во Flutter

Итак, вот код. Ошибка заключается в том, что вызов функции loadSounds извне класса возвращает пустой список. Но когда loadSounds вызывается из loadcategories, он работает нормально и возвращает список, содержащий экземпляры Sound. Даже при выводе переменной звуков в функцию loadSounds печатается пустой список.

      class AudioRepository {
  List<Category> categories = <Category>[];
  List<Sound> sounds = <Sound>[];

  Future<String> _loadCategoriesAsset() async =>
      await rootBundle.loadString(Assets.soundsJson);

  Future<List<Category>> loadCategories() async {
    if (categories.isNotEmpty) {
      return categories;
    }

    String jsonString = await _loadCategoriesAsset();
    categories.clear();
    categories.addAll(categoryFromJson(jsonString));
    categories.map((c) => sounds.addAll(c.sounds)).toList();
  
    loadSounds('1');
    return categories;
  }

  Future<List<Sound>> loadSounds(String categoryId) async {
    print(sounds);
    return sounds
        .where((sound) => sound.id.substring(0, 1) == categoryId)
        .toList();
  }
}

Вывод при вызове из loadCategories выглядит следующим образом:

      [Instance of 'Sound', Instance of 'Sound', Instance of 'Sound', Instance of 'Sound', Instance of 'Sound', Instance of 'Sound']

Я получаю доступ к нему вне класса следующим образом:

      final _sounds = await repository.loadSounds(event.categoryId);

Вывод при вызове извне или печати из функции loadSounds выглядит следующим образом:

      []

Так в чем тут проблема. Я не могу понять, почему функция loadSounds работает при вызове из loadCategories внутри класса и никак иначе.

Вот класс звука:

      import 'package:meta/meta.dart';

class Sound {
  String id;
  String title;

  Sound({
    @required this.id,
    @required this.title,
  });

  Sound copyWith({
    String id,
    String title,
  }) =>
      Sound(
        id: id ?? this.id,
        title: title ?? this.title,
      );

  factory Sound.fromJson(Map<String, dynamic> json) => Sound(
        id: json["id"],
        title: json["title"]
      );

  Map<String, dynamic> toJson() =>
      {"id": id, "title": title};
}

Sounds.json:

      [
  {
    "id": "1",
    "title": "City",
    "sounds": [
      {
        "id": "101",
        "title": "Airplane"
      },
      {
        "id": "102",
        "title": "Car"
      },
    ]
  },
  {
    "id": "2",
    "title": "Meditation",
    "sounds": [
      {
        "id": "201",
        "title": "Bells"
      },
      {
        "id": "202",
        "title": "Bowl"
      }
    ]
  },
]

3 ответа

Решение

Если ты не позвонишь repository.loadCategories() перед звонком loadSounds(), у вас не будет ничего в вашей переменной звуков, поскольку вы назначаете значения только в своей loadCateogries() функция.

Является ли ваша переменная репозитория синглтоном и вызывали ли вы для нее loadCategories?

Кроме того, я бы не стал писать вот так:

      categories.map((c) => sounds.addAll(c.sounds)).toList();

В toList() метод не очень полезен, и функцию карты следует использовать больше для преобразования чего-либо (например, сопоставление String с Int).

Я хотел бы использовать :

      categories.forEach((c)=> sounds.addAll(c.sounds));

используйте provider и ChangeNotifier - лучший способ. ваш код будет таким

      class AudioRepository extends ChangeNotifier {
  List<Category> categories = <Category>[];
  List<Sound> sounds = <Sound>[];

  Future<String> _loadCategoriesAsset() async =>
      await rootBundle.loadString(Assets.soundsJson);

  Future<List<Category>> loadCategories() async {
    if (categories.isNotEmpty) {
      return categories;
    }

    String jsonString = await _loadCategoriesAsset();
    categories.clear();
    categories.addAll(categoryFromJson(jsonString));
    categories.map((c) => sounds.addAll(c.sounds)).toList();

    //notify listeners
    notifyListeners();
    ////
    loadSounds('1');
    return categories;
  }

  Future<List<Sound>> loadSounds(String categoryId) async {
    print(sounds);
    return sounds
        .where((sound) => sound.id.substring(0, 1) == categoryId)
        .toList();
  }
}

для извлечения данных извне следует поместить следующий код в Build() метод.

      final _arp = Provider.of<AudioRepository>(context, listen: true);

print(_arp._sounds);

Это может быть ошибка в предложении where. Потому что условие неправильное. попробуй это:

      return sounds
        .where((sound) => sound.id[0] == categoryId)
        .toList();
Другие вопросы по тегам