Маршрут не обновляется должным образом в веб-приложении Flutter - PullRequest
0 голосов
/ 05 августа 2020

У меня есть веб-приложение, написанное на Flutter, в котором маршруты не обновляются, как я ожидал.

Контекст

Приложение изначально было написано для мобильных устройств, но теперь я пытаюсь преобразовать его в веб-приложение. Базовая c архитектура приложения не изменилась, но поведение приложения на Chrome не такое, как на Android / iOS. Я объясню ниже.

Архитектура

Инициализация приложения происходит следующим образом:

  1. Функция верхнего уровня runApp возвращает класс «_ServiceLayer», который в основном просто создает набор служб, к которым можно получить доступ в приложении через интерфейс поставщика. В моем упрощенном примере я только что создал одну службу, которая увеличивает счетчик.
  2. Следующий уровень - это виджет «_Dispatcher», который по сути определяет состояние приложения из одной из служб.
  3. В зависимости от состояния приложения я возвращаю MaterialApp с другим initialRoute. Если состояние приложения изменяется, _Dispatcher прослушивает и сгенерирует новое приложение MaterialApp с другим initialRoute.

Рабочий пример

// main.dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  return runApp(_ServiceLayer());
}

class CounterService extends ChangeNotifier {
  int counter = 0;
  increment() {
    counter += 1;
    notifyListeners();
  }
} 

class _ServiceLayer extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (context) => CounterService(), lazy: false),
      ],
      child: _Dispatcher(),
    );
  }
}

class _Dispatcher extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    _app(String initialRoute) {
      return myMaterialApp(initialRoute);
    }

    int current_value = context.select((CounterService c) => c.counter);
    if (current_value % 2 == 0) return _app('even');
    if (current_value % 2 == 1) return _app('odd');

    return _app('error'); // should never get here, so did not implement
  }
}

class myMaterialApp extends StatelessWidget {
  String initialRoute;

  myMaterialApp(this.initialRoute);

  @override
  Widget build(BuildContext context) {
    print("Generating $initialRoute route"); // <-- ALTERNATES EVEN & ODD
    return MaterialApp(
      title: 'Example',
      initialRoute: initialRoute,
      routes: {
        'even': (BuildContext context) => EvenPage(), 
        'odd': (BuildContext context) => OddPage(), 
      },
    );
  }
}

class EvenPage extends Page {
  String title = 'Even';
}

class OddPage extends Page {
  String title = 'Odd';
}

abstract class Page extends StatelessWidget { 
  String title;

  @override
  Widget build(BuildContext context) {
    var counterService = Provider.of<CounterService>(context, listen: false);
    int ctr = counterService.counter;
    return Column(
      children: [
        Text(title), // <-- ALWAYS SAYS EVEN
        Text("Counter = ${ctr}"),
        RaisedButton(
          child: Text("Press me"),
          onPressed: () {
            counterService.increment();
          }
        ),
      ],
    ); 
  }
}

Проблема

Проблема заключается в следующем: если вы несколько раз нажимаете кнопку, счетчик будет увеличиваться, как ожидалось, а операторы печати в консоли будут чередоваться между четным и нечетным:

Generating even route
Generating odd route
Generating even route
etc.

Это, похоже, означает, что создается приложение MaterialApp заново с каждой кнопкой pu sh, что является ожидаемым поведением. Однако , заголовок страницы всегда "Четный", как будто OddPage вообще никогда не строится!

Flutter Doctor

Результат работы Flutter Doctor:

[✓] Flutter (Channel beta, 1.20.0-7.4.pre, on Mac OS X 10.15.3 19D76, locale en-US)
    • Flutter version 1.20.0-7.4.pre at ...
    • Framework revision 916c3ac648 (3 days ago), 2020-08-01 09:01:12 -0700
    • Engine revision d6ee1499c2
    • Dart version 2.9.0 (build 2.9.0-21.10.beta)


[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    • Android SDK at ...
    • Platform android-29, build-tools 28.0.3
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 11.6)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 11.6, Build version 11E708
    • CocoaPods version 1.8.4

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.0)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 47.1.2
    • Dart plugin version 193.7361
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)

[✓] Connected device (2 available)
    • Web Server (web) • web-server • web-javascript • Flutter Tools
    • Chrome (web)     • chrome     • web-javascript • Google Chrome 84.0.4147.105

• No issues found!

Вопросы

  1. Что происходит? Создается новый MaterialApp или нет?
  2. Предлагаете ли вы другой дизайн? Я подумал, нужно ли сгенерировать один MaterialApp с initialRoute, эффективно выполняющим работу _Dispatcher, но по причинам, которые я не помню, я не преследовал его. Может мне стоит пересмотреть этот подход?
...