modal_bottom_sheet icon indicating copy to clipboard operation
modal_bottom_sheet copied to clipboard

Modal Bottom Sheet get disposed when a new screen is push

Open LeGoffMael opened this issue 3 years ago • 2 comments

First thank you for this great library.

I am using the plugin inside my router, it works extremely well but there is a weird behavior when pushing a new route. When pushing a new route from the modal page, the modal page itself get disposed, then get init again.

You can see the problem in this log generated from the video attached :

flutter: 🏠 _MyHomePageState initState
flutter: 📃 _ModalScreenState initState
flutter: 👷‍♂️ _NewScreenState initState
flutter: 📃 _ModalScreenState dispose <-- here is the error
flutter: 🌗  _LastScreenState initState
flutter: 🌗  _LastScreenState dispose
flutter: 📃 _ModalScreenState initState
flutter: 👷‍♂️ _NewScreenState dispose
flutter: 📃 _ModalScreenState dispose

https://user-images.githubusercontent.com/22376981/177247106-5fb97c11-89e0-4e3c-8d05-aee0527f1ad9.MP4

Minimal reproducible example

router

import 'package:example_modal_route_error/main.dart';
import 'package:flutter/material.dart';
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';

class Routes {
  static const home = '/';
  static const modal = '/modal';
  static const newScreen = '$modal/newScreen';
  static const lastScreen = '$newScreen/lastScreen';
}

typedef RouteResolver = Route<dynamic> Function(RouteSettings settings);

class MyRouter {
  static Route<dynamic>? onGenerateRoute(RouteSettings settings) {
    final routePage = _pagesMap[settings.name];
    return routePage?.call(settings);
  }

  static final _pagesMap = <String, RouteResolver>{
    Routes.home: (settings) {
      return MaterialPageRoute(
        settings: settings,
        builder: (context) => const MyHomePage(),
      );
    },
    Routes.modal: (settings) {
      return ModalBottomSheetRoute(
        expanded: true,
        settings: settings,
        containerBuilder: (_, __, child) => BarBottomSheet(child: child),
        builder: (context) => const ModalScreen(),
      );
    },
    Routes.newScreen: (settings) {
      return MaterialPageRoute(
        settings: settings,
        builder: (context) => const NewScreen(),
      );
    },
    Routes.lastScreen: (settings) {
      return MaterialPageRoute(
        settings: settings,
        builder: (context) => const LastScreen(),
      );
    },
  };
}

main

import 'package:example_modal_route_error/router.dart';
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter example error modal route',
      theme: ThemeData(primarySwatch: Colors.blue),
      onGenerateRoute: (RouteSettings settings) =>
          MyRouter.onGenerateRoute(settings),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    print('🏠 _MyHomePageState initState');
    super.initState();
  }

  @override
  void dispose() {
    print('🏠 _MyHomePageState dispose');
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter example error modal route')),
      body: Center(
        child: TextButton(
          onPressed: () => Navigator.pushNamed(context, Routes.modal),
          child: const Text('Tap to open modal'),
        ),
      ),
    );
  }
}

class ModalScreen extends StatefulWidget {
  const ModalScreen({super.key});

  @override
  State<ModalScreen> createState() => _ModalScreenState();
}

class _ModalScreenState extends State<ModalScreen> {
  @override
  void initState() {
    print('📃 _ModalScreenState initState');
    super.initState();
  }

  @override
  void dispose() {
    print('📃 _ModalScreenState dispose');
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('📃 Modal screen')),
      body: Center(
        child: TextButton(
          onPressed: () => Navigator.pushNamed(context, Routes.newScreen),
          child: const Text('Tap to push new route'),
        ),
      ),
    );
  }
}

class NewScreen extends StatefulWidget {
  const NewScreen({super.key});

  @override
  State<NewScreen> createState() => _NewScreenState();
}

class _NewScreenState extends State<NewScreen> {
  @override
  void initState() {
    print('👷‍♂️ _NewScreenState initState');
    super.initState();
  }

  @override
  void dispose() {
    print('👷‍♂️ _NewScreenState dispose');
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('👷‍♂️ New screen')),
      body: Center(
        child: TextButton(
          onPressed: () => Navigator.pushNamed(context, Routes.lastScreen),
          child: const Text('Tap to push last route'),
        ),
      ),
    );
  }
}

class LastScreen extends StatefulWidget {
  const LastScreen({super.key});

  @override
  State<LastScreen> createState() => _LastScreenState();
}

class _LastScreenState extends State<LastScreen> {
  @override
  void initState() {
    print('🌗  _LastScreenState initState');
    super.initState();
  }

  @override
  void dispose() {
    print('🌗  _LastScreenState dispose');
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('🌗 Last screen')),
      body: const Center(child: Text('This is the last screen')),
    );
  }
}

i am using a the latest version of the plugin 2.1.0 and flutter 3.0.3.

LeGoffMael avatar Jul 05 '22 04:07 LeGoffMael

This error does not occurs while using 2.0.1 version.

LeGoffMael avatar Jul 05 '22 04:07 LeGoffMael

I can confirm this behaviour. Reverting to 2.0.1 and you don't get a dispose. If the pane you push is something like tab view, you basically lose all state of which tab was pushed etc.

jonmountjoy avatar Aug 13 '22 11:08 jonmountjoy