onesignal: переход к экрану при открытии уведомления.Я получаю эту ошибку: setState () или markNeedsBuild () вызывается во время сборки - PullRequest
0 голосов
/ 09 февраля 2019

Сценарий:
Мне нужно открыть определенный экран при открытии уведомления о сигнале.

Это то, что я попробовал первым:

import ...;

void main() async {
  final persistor = Persistor<AppState>(
    storage: FlutterStorage(),
    serializer: JsonSerializer<AppState>(AppState.fromJson),
  );

  final initialState = await persistor.load();

  if (initialState.isLoggedIn) {
    initialState.silentlyLogin();
  }

  final store = Store<AppState>(
    appReducer, /* Function defined in the reducers file */
    initialState: initialState ?? AppState.initial(),
    middleware: [persistor.createMiddleware()],
  );

  FlutterError.onError = (FlutterErrorDetails details) async {
    if (isInDebugMode) {
      FlutterError.dumpErrorToConsole(details);
    } else {
      Zone.current.handleUncaughtError(details.exception, details.stack);
    }
  };

  intl_local_date_data.initializeDateFormatting();
  Intl.defaultLocale = 'it_IT';

  OneSignal.shared.setLogLevel(OSLogLevel.verbose, OSLogLevel.none);

  var settings = {
    OSiOSSettings.autoPrompt: false,
    OSiOSSettings.promptBeforeOpeningPushUrl: true
  };

  await OneSignal.shared.init("...", iOSSettings: settings);

  OneSignal.shared.setInFocusDisplayType(OSNotificationDisplayType.notification);

  runZoned<Future<void>>(() async {
    runApp(MyApp(store: store));
  }, onError: (error, stackTrace) {
    _reportError(error, stackTrace);
  });
}

class MyApp extends StatefulWidget {
  final Store<AppState> store;

  const MyApp({Key key, this.store}) : super(key: key);

  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    initPlatformState();
  }

  Future<void> initPlatformState() async {
    if (!mounted) return;

    OneSignal.shared.setNotificationReceivedHandler((OSNotification notification) {});

    OneSignal.shared.setNotificationOpenedHandler((OSNotificationOpenedResult result) {
      // NOTHING HAPPENS: THE HOMESCREEN IS OPENED ANYWAY
      Navigator.push(
        context,
        MaterialPageRoute(
          builder: (context) => AnotherScreen(),
        ),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return new  StoreProvider<AppState>(
        store: widget.store,
        child: new MaterialApp(
            initialRoute: '/',
            routes: {
              '/': (context) => HomeScreen(),
            }
        )
    );
  }
}

Проблема с этим кодом заключается в том, что при открытии уведомления ничего не происходит.
Даже если я включаю вызов Navigate.push вsetNotificationOpenedHandler функция, приложение по-прежнему открывает HomeScreen.

Поэтому я попытался использовать другой подход :
Каждый раз, когда я открываю уведомление, я отправляю избыточное действие, и в HomeScreenМне удается открыть другой экран.

Я изменил функцию setNotificationOpenedHandler следующим образом:

OneSignal.shared.setNotificationOpenedHandler((OSNotificationOpenedResult result) {
    widget.store.dispatch(new Action(result.notification.payload.additionalData["id"]));
});

Действие отправлено правильно.В HomeScreen я попытался изменить этап редукса с помощью этого кода:

import ...

class HomeScreen extends StatefulWidget {

  HomeScreen({Key key}) : super(key: key);

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

class _HomeScreenState extends State<HomeScreen> {

  @override
  void initState() {
    super.initState();
  }

  //...

  @override
  Widget build(BuildContext context) {
    return StoreConnector<AppState, AppState>(
      converter: (store) => store.state,
      builder: (context, appState) {

        // HERE I MANAGE CHANGE OF REDUX STATE TO NAVIGATE
        if (appState.id != null) {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => AnotherScreen(),
            ),
          );
        }

        return DefaultTabController(
          length: 3,
          // ecc...
        );
      },
    );
  }
}

С этим кодом я получаю эту ошибку:

setState() or markNeedsBuild() called during build
...