Home > Software engineering >  How to reach arguments outside of the build in flutter
How to reach arguments outside of the build in flutter

Time:10-06

I have learned that it brings problems when initating a future- or streambuilder inside the build of a widget since it will lead to unwanted fetching of data.

To do this you pass the stream outside of the build-method. But this leads to another problem. In my case I have to get an id-argument from the last widget but that can only be reached inside the build. I have searched the internet for explanations on how to solve this but I cant find an easy and clean explanation on the best way to do this. A good solution that initialize the future with the build outside of the build.

My material app:

MaterialApp(
            routes: appRoutes,
          );

My routes table:

var appRoutes = {
  Screen1.routeName: (context) => Screen1(),
  Screen2.routeName: (context) => Screen2(),
};

How I send the argument from screen1:

onTap: () {
        Navigator.of(context).pushNamed(
          Screen2.routeName,
          arguments: id,
        );
      },

screen2: (which doesnt work this way)

class Screen2 extends StatefulWidget {
  static const routeName = '/screen2';

  @override
  State<Screen2> createState() => _Screen2State();
}

class _Screen2State extends State<Screen2> {
  @override
  final String id = ModalRoute.of(context)!.settings.arguments as String; <====== Impossible
  final _stream = FirestoreService().getData(id);

  Widget build(BuildContext context) {
    return FutureBuilder<Map>(
        future: _stream,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            print('succes');
          } else {
            print('Fail');
          }
        });
  }
}

CodePudding user response:

Way1: late keyword (unstable)

Use late keyword for lazy initialiation of your argument, stream.

class Screen2 extends StatefulWidget {
  static const routeName = '/screen2';

  @override
  State<Screen2> createState() => _Screen2State();
}

class _Screen2State extends State<Screen2> {
  @override
  late final String id = ModalRoute.of(context)!.settings.arguments as String; <====== Impossible
  late final _stream = FirestoreService().getData(id);

  Widget build(BuildContext context) {
    ...
  }
}

Way2: onGerateRoute constructor (good)

You can check this answer for using onGenerateRoute. It is more proper way.

Way3: Create extraction delegation screen (good)

In the docs, the best practice is creating a delegation screen for extract arguments.

It parse argument in build method and pass it to new screen.

// A Widget that extracts the necessary arguments from
// the ModalRoute.
class ExtractArgumentsScreen extends StatelessWidget {
  const ExtractArgumentsScreen({super.key});

  static const routeName = '/extractArguments';

  @override
  Widget build(BuildContext context) {
    // Extract the arguments from the current ModalRoute
    // settings and cast them as ScreenArguments.
    final args = ModalRoute.of(context)!.settings.arguments as ScreenArguments;

    return Scaffold(
      appBar: AppBar(
        title: Text(args.title),
      ),
      body: Center(
        child: Text(args.message),
      ),
    );
  }
}
  • Related