PageStorageKey не загружается между переходами - PullRequest
0 голосов
/ 01 августа 2020

Я просмотрел практически всю информацию, которую смог найти по этому вопросу, но ни одно из решений, похоже, не работает для меня. У меня есть постоянная верхняя панель навигации, через которую я передаю представления с помощью функции построителя MaterialApp, как показано ниже. Внутри этого класса NavFrame у меня просто две кнопки для переключения между представлениями. Второе представление имеет GridView с привязанным к нему PageStorageKey. Если вы прокручиваете и переключаетесь между представлениями, вы увидите, что позиция прокрутки не загружается при возврате к сетке в представлении 2. Я использую последний пакет Auto-Route для создания своих маршрутов.

main.dart

void main() {
  runApp(MyApp());
}

final _navKey = GlobalKey<NavigatorState>();

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'PageStorageKey Debugging',
      theme: ThemeData(
        primarySwatch: Colors.green,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      initialRoute: Routes.view1,
      navigatorKey: _navKey,
      onGenerateRoute: Router().onGenerateRoute,
      builder: (context, child) => NavFrame(_navKey, child),
    );
  }
}

nav_frame.dart

class NavFrame extends StatelessWidget {
  final Widget child;
  final GlobalKey<NavigatorState> _navKey;
  const NavFrame(this._navKey, this.child, {Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Positioned(
            top: 0,
            left: 0,
            right: 0,
            child: Container(
              color: Colors.black,
              height: 100,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  RaisedButton(
                    onPressed: () {
                      _navKey.currentState.pushReplacementNamed(Routes.view1);
                    },
                    child: Text('View 1'),
                  ),
                  SizedBox(
                    width: 50,
                  ),
                  RaisedButton(
                    onPressed: () {
                      _navKey.currentState.pushReplacementNamed(Routes.view2);
                    },
                    child: Text('View 2'),
                  ),
                ],
              ),
            )),
        Positioned(
          top: 100,
          left: 0,
          right: 0,
          bottom: 0,
          child: Container(
            child: child,
          ),
        ),
      ],
    );
  }
}

view1.dart

class View1 extends StatelessWidget {
  const View1({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
            child: Container(
          color: Colors.blue,
        ))
      ],
    );
  }
}

view2.dart

class View2 extends StatefulWidget {
  const View2({Key key}) : super(key: key);

  @override
  _View2State createState() => _View2State();
}

class _View2State extends State<View2>
    with AutomaticKeepAliveClientMixin<View2> {
  final bucket = PageStorageBucket();

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Column(
      children: [
        Expanded(
          child: GridView.builder(
            key: new PageStorageKey('test-key'),
            addAutomaticKeepAlives: true,
            padding: EdgeInsets.all(30),
            shrinkWrap: true,
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 1,
              childAspectRatio: 2,
              crossAxisSpacing: 30,
              mainAxisSpacing: 30,
            ),
            itemCount: 10,
            itemBuilder: (BuildContext context, int index) {
              return Container(
                  decoration: BoxDecoration(
                    border: Border.all(width: 1.5, color: Colors.black),
                    borderRadius: BorderRadius.all(Radius.circular(10.0)),
                  ),
                  child: Center(
                    child: Material(
                      child: Text(
                        index.toString(),
                        style: TextStyle(fontSize: 20),
                      ),
                    ),
                  ));
            },
          ),
        )
      ],
    );
  }

  @override
  bool get wantKeepAlive => true;
}

router.dart

@MaterialAutoRouter(
  generateNavigationHelperExtension: true,
  routes: <AutoRoute>[
    MaterialRoute(page: View1, initial: true),
    MaterialRoute(page: View2, path: "/view2"),
  ],
)
class $Router {}

pubspe c .yaml

name: PageStorageKeyTest
description: Debugging PageStorageKey.

publish_to: "none"

version: 1.0.0+1

environment:
  sdk: ">=2.7.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter

  # Navigation
  auto_route: 0.6.6

  # Cupertino
  cupertino_icons: ^0.1.3

dev_dependencies:
  flutter_test:
    sdk: flutter

  build_runner: 1.10.1
  auto_route_generator:

flutter:
  uses-material-design: true

Как уже упоминалось, я пробовал много различных предлагаемых решений, которые мне удалось найти. В настоящее время в View2 вы увидите, что я использую AutomaticKeepAliveCluentMixin с wantKeepAlive, установленным в true. Я также убедился, что позвонил по номеру super.build(context), как я видел в одном вопросе здесь. Я также пробовал использовать PageStoreBucket практически во всех местах, которые я могу себе представить, и, похоже, он ничего не делает. (В настоящее время не используется в приведенном выше коде). Я пытался установить для maintainState значение true в MaterialRoute. В моем фактическом проекте, где я сталкиваюсь с этим, я использую архитектуру Stacked и даже пытался передавать ключи через viewModel, а построитель viewModel строил только один раз, и, похоже, ничто не помогло. Выполнение приведенного выше кода должно привести к возникновению именно той проблемы, с которой я столкнулся. Я также использую последнюю версию разработчика (1.21.0-1.0.pre). Есть предложения?

1 Ответ

0 голосов
/ 02 августа 2020

Я неправильно смотрел на это с точки зрения UX. Вы можете добиться желаемого эффекта от того, о чем я говорил, используя scrollController и сохранив смещение в глобальной переменной или что-то в этом роде и просто переназначив его в методе initState параметру initialOffset scrollController. Я лично использовал многослойную архитектуру и сохранил смещение в классе обслуживания с помощью reactiveServiceMixin. Это работает для того, что я описал, но это не то, чего я на самом деле хотел, чего я не осознавал, пока не сделал это и не убедился в этом сам. Если вы используете навигатор для перехода, например, на страницу магазина, а затем go в блог, а затем снова щелкаете магазин в навигаторе, вы, вероятно, ожидаете, что вернетесь в начало магазина. При нажатии кнопки возврата со страницы блога на go обратно в магазин вы, вероятно, ожидаете, что он сохранит положение прокрутки. Оказывается, он уже делал все это до реализации этого.

...