FutureBuilder останавливает мое приложение, потому что оно ожидает загрузки файла перед сборкой - PullRequest
0 голосов
/ 06 июня 2019

Я пишу очень простое приложение для чтения общедоступных книг. Я включил файл .txt, содержащий книгу, в ресурсы моего приложения. Так как книга довольно длинная и требует много времени для загрузки, я пытался использовать FutureBuilder, который будет отображать круговой индикатор прогресса во время загрузки книги, однако, когда я нажимаю на кнопку, чтобы открыть книгу, приложение зависает, пока книга загружается вместо перехода на страницу книги и показывает индикатор прогресса во время загрузки книги, как мне хотелось бы.

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

FutureBuilder(
                  future: text, //Future<String>
                  builder: (context,snapshot) {
                    if (snapshot.connectionState==ConnectionState.done) {
                      return Text(
                        snapshot.data,
                        style: TextStyle(fontSize: 20),);
                    }
                    else {
                      return CircularProgressIndicator();
                    }
                  },

                )

Похоже, что FutureBuilder просто пытается построить с текстом, а не без него, и добавляет его позже, как и положено. Как мне сказать это сделать?

Ответы [ 2 ]

1 голос
/ 07 июня 2019

Дротик в основном однопоточный.Поэтому, когда вы читаете текст, он делает это в том же потоке, что и пользовательский интерфейс, и поэтому замедляет его.Использование будущего означает, что вызов может быть делегирован на более позднее время (в зависимости от того, как вы его запланировали), но он все еще выполняется в том же потоке.

То, что вы хотите сделать, это использовать Изолируйте и выполните чтение файла.Получив файл (и выполнив любую необходимую вам обработку), вы сможете передать его обратно в класс Text, и он должен быть быстрее - хотя, если вы имеете дело с очень большим объемом текста, он все еще можетзаикаться немного, так как класс Text все еще должен обрабатывать весь текст.Если это произойдет, я бы порекомендовал разбить текст на части (глава / абзац?) И использовать несколько текстовых и / или форматированных объектов для отображения его в списке.

Самый простой способ использовать изолятор вflutter - это функция `compute '.

Тогда в вашем будущем будет что-то вроде этого:

await compute(readFile, <path to file>);

Обратите внимание, что вход и выход computeимеют некоторые ограничения, так как он использует SendPort Isolate под капотом:

Содержимое сообщения может быть следующим: примитивные значения (null, num, bool, double, String), экземплярыSendPort, а также списки и карты, элементами которых являются любые из них.Список и карты также могут быть циклическими.

0 голосов
/ 07 июня 2019

Я думаю, что проблема здесь:

if (snapshot.connectionState == ConnectionState.done) {
  return Text(snapshot.data, style: TextStyle(fontSize: 20));
}

ConnectionState.done устанавливается сразу после подключения потока (я предполагаю, что вы используете поток), так что условие всегда выполняется.Я думаю, что лучше использовать Snapshot.hasData для проверки, например, так:

FutureBuilder<String>(
    future: futureStream,
    builder: (context, snapshot) {
      if (snapshot.hasData) {
        return Text(snapshot.data);
      } else {
        return CircularProgressIndicator();
      }
    },
);
...