Flatter Drawer ленивая загрузка при извлечении в пользовательский виджет - PullRequest
0 голосов
/ 28 августа 2018

У меня на главной странице есть ящик, наполненный содержанием и логикой. Например, мне нужно получить изображение, получить некоторые данные из Интернета и так далее. После извлечения Drawer в новый MyCustomDrawerWidget, который расширяет StatefulWidget, его состояние имеет функцию build, которая выглядит следующим образом:

@override
Widget build(BuildContext context) {
  return Drawer(
    child: ...
  );
}

My HomePageState имеет функцию build, которая выглядит следующим образом:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Home page'),
    ),
    drawer: MyCustomDrawerWidget(),
    body: ...
  );
}

После рефакторинга кода, подобного этому, я заметил, что ящик не инициализируется при загрузке страницы. Он инициализируется сразу после того, как я открою ящик, и это плохо, потому что пользователь должен ждать загрузки данных.

Есть ли способ настроить загрузку ящика для инициализации вместе со страницей?

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

Проблема с наличием Ящика на главной странице :

  • Контент, больше логики, загрузка изображения, получение данных из Интернета и т. Д.

Проблема с Ящиком в MyCustomDrawerWidget :

  • Время загрузки, плохой пользовательский опыт

Я бы предложил получить hybrid подход для решения проблемы.

  • Запуск сетевых вызовов в MainPage
  • Отправка future на MyCustomDrawerWidget (Если пользователь открывает ящик до завершения сетевого вызова, мы можем показать загрузчик на основе будущего значения)
  • Переместите логику и содержимое, относящиеся к ящику, в MyCustomDrawerWidget.

    class MyCustomDrawerWidget extends StatelessWidget {
      var _future;
    
      MyCustomDrawerWidget(this._future);
    
      @override
      Widget build(BuildContext context) {
        return new Drawer(
          child: FutureBuilder(
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                var data = snapshot.data;
                return new Text(data);
              } else {
                return new Text("loading");
              }
            },
            future: _future,
          ),
        );
      }
    }
    

А в MainPage

@override
Widget build(BuildContext context) {
  val future = Future.delayed(Duration(seconds: 10), () => "new value") //network call
  return Scaffold(
      appBar: AppBar(
        title: Text('Home page'),
      ),
      drawer: MyCustomDrawerWidget(future),
      body: ...
  );
}

Надеюсь, это поможет.

0 голосов
/ 28 августа 2018

У меня была такая же проблема. Scaffold прикрепляет выдвижной ящик только при необходимости.

Решение: переместить логику загрузки данных в родительский виджет. Вы все еще можете инкапсулировать его в отдельный класс модели (например, DrawerModel), но этот класс должен быть создан при инициализации родительского виджета. Держите это в State родителя. Передайте DrawerModel в ваш виджет ящика.

Вы должны быть немного осторожнее при использовании потоков и фьючерсов, потому что те, как правило, не могут быть переподписаны. Я бы порекомендовал вам использовать StreamBuilder в виджете ящика, который подключен к BehaviorSubject в вашем DrawerModel.

Это очень похоже на паттерн BLoC. Вам нужен пример кода?

...