Получение инициализированных значений параметров даже после их изменения

Ну, я застрял в этой проблеме. У меня есть код для (), который принимает queueиграть. Я получаю очередь из. Проблема в очереди в audioservice.dartкод оказывается инициализированным даже после того, как я его изменил. Например, если я инициализирую его как пустой список, а затем изменяю его, используя ответ от API и функцию для его форматирования, очередь изменяется, но код показывает, что он пуст. Если я инициализирую его жестко запрограммированной очередью, то получится такая же жестко запрограммированная очередь даже после ее изменения. Даже любой другой параметр, к которому я пытаюсь получить доступ из playlist.dart в audioplayer.dartоказывается таким же, как инициализированный. Я не могу понять здесь проблему.

Это код для AudioService. Как вы можете видеть в строках 349 и 491, я предоставляю playlist.mediaItems в качестве очереди.

Это код в файле списка воспроизведения (playlist.dart):

      library now_playing.globals;

import 'dart:typed_data';
import 'package:audio_service/audio_service.dart';

List<MediaItem> mediaItems = [];
List tempResponse = [];

class PlaySongClass {
  bool check() {
    nowPlaying[playIndex].toString().startsWith('{')
        ? offline = false
        : offline = true;
    return offline;
  }

  setValues(response) {
    response == [] ? response = tempResponse : response = response;
    List<MediaItem> tempList = [];
    for (int i = 0; i < response.length; i++) {
      var tempDict = MediaItem(
          id: response[i]['id'],
          album: response[i]['more_info']['album'],
          duration: Duration(
              seconds: int.parse(response[i]['more_info']['duration'])),
          title: response[i]['title']
              .toString()
              .replaceAll("&amp;", "&")
              .replaceAll("&#039;", "'")
              .replaceAll("&quot;", "\""),
          artist: response[i]["more_info"]["artistMap"]["primary_artists"][0]
                  ["name"]
              .toString()
              .replaceAll("&amp;", "&")
              .replaceAll("&#039;", "'")
              .replaceAll("&quot;", "\""),
          artUri:
              response[i]['image'].toString().replaceAll("150x150", "500x500"));
      tempList.add(tempDict);
    }
    // print('TempList is $tempList');
    mediaItems = tempList;
    print('queue has been setted');
    print(tempList);
    return tempList;
  }
}
final playSong = PlaySongClass();

Здесь вы можете увидеть List<MediaItem> mediaItemsэто пустой список. Теперь, если я использую функцию setValues из класса PlaySongClass с помощью playlist.playSong.setValues изменить значение List<MediaItem> затем в audioserviceкод, отображается пустой список. Если я жестко запрограммировал его со списком, он будет работать с тем же жестко запрограммированным списком.

1 ответ

Решение

audio_service управляет вашим BackgroundAudioTask

в отдельном изоляторе. В README это написано так:

Обратите внимание, что ваш пользовательский интерфейс и фоновая задача выполняются в отдельных изоляторах и не разделяют память. Единственный способ общения - передача сообщений. Ваш интерфейс Flutter будет использовать только AudioService

API для связи с фоновой задачей, в то время как ваша фоновая задача будет использовать только AudioServiceBackground API для взаимодействия с пользовательским интерфейсом и другими клиентами.

Ключевым моментом здесь является то, что изоляты не разделяют память. Если вы установите «глобальную» переменную в изоляторе пользовательского интерфейса, она не будет установлена ​​в фоновой изоляции, поскольку фоновая изоляция имеет свой собственный отдельный блок памяти. Вот почему ваша глобальная переменная равна нулю. На самом деле это не одна и та же переменная, потому что теперь у вас есть две копии переменной: одна в изоляте пользовательского интерфейса, который был установлен со значением, а другой в фоновом изоляте, который (пока) не был установлен со значением .

Теперь ваш фоновый изолятор «позже» устанавливает свою собственную копию переменной очереди на что-то, и это происходит через API передачи сообщений, где вы передаете очередь из изолятора пользовательского интерфейса в updateQueue

а фоновый изолят получает это сообщение и сохраняет его в своей собственной копии переменной в. Если бы вы распечатали очередь после этого момента, она больше не была бы нулевой.

В вашем файле также есть строка, в которой вы пытаетесь установить очередь, хотя вам, вероятно, следует удалить этот код и разрешить только установку очереди. Вы не должны пытаться получить доступ к очереди в onStart

поскольку ваша очередь не получит свое значение до. Если вы хотите избежать какого-либо исключения нулевого указателя до его установки, вы можете инициализировать очередь в фоновом изоляторе пустым списком, и в конечном итоге он будет заменен непустым списком в onUpdateQueue никогда не быть нулевым.

Я бы также посоветовал вам избегать queue

глобальная переменная. Глобальные переменные, как правило, плохие, но в этом случае вас может сбить с толку мысль, что эта переменная очереди одинакова как в пользовательском интерфейсе, так и в фоновом изоляторе, тогда как на самом деле каждый изолят будет иметь свою собственную копию переменной, возможно, с разными значения. Таким образом, ваш код будет более понятным, если вы сделаете две отдельные «локальные» переменные. Один внутри пользовательского интерфейса, а другой - в фоновой задаче.

Еще одно предложение: вы должны отметить, что методы в API передачи сообщений являются асинхронными. Вы должны дождаться запуска аудиоуслуги, прежде чем отправлять ей сообщения, например, настраивая очередь. И вы должны дождаться, пока будет установлена ​​очередь, прежде чем пытаться играть из очереди:

      await AudioService.start(....);
// Now the service has started, it is safe to send messages.
await AudioService.updateQueue(...);
// Now the queue has been updated, it is safe to play from it.
Другие вопросы по тегам