Home > database >  Flutter, writing clean code, are you supposed to extract widgets out of the build method even if it&
Flutter, writing clean code, are you supposed to extract widgets out of the build method even if it&

Time:11-29

I understand that if I have a widget that repeats, I should break it out into a function.

But what if it's only used once, but it's very big? Do I still extract it?

Example:

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      drawer: SizedBox(
            width: MediaQuery.of(context).size.width * 0.48,
            child: Drawer(
                elevation: 10,
                backgroundColor: Theme.of(context)
                    .colorScheme
                    .background
                    .withOpacity(0.95),
                child: ListView(
                  children: [
                    ListTile(
                      leading: const Icon(
                        Icons.shopping_cart_outlined,
                        size: 22,
                      ),
                      title: Text('Shop',
                          style: Theme.of(context).textTheme.labelSmall),
                      onTap: () => Navigator.of(context).push(
                          MaterialPageRoute(
                              builder: (_) => const marketView())),
                    ),
                    ListTile(
                      leading: const Icon(
                        Icons.timeline_rounded,
                        size: 22,
                      ),
                      title: Text('To Do',
                          style: Theme.of(context).textTheme.labelSmall),
                      onTap: () => Navigator.of(context).push(
                          MaterialPageRoute(
                              builder: (_) => const todo())),
                    ),
                    ListTile(
                        leading: const Icon(
                          Icons.square,
                          size: 22,
                        ),
                        title: Text('Calendar',
                            style: Theme.of(context).textTheme.labelSmall),
                        onTap: () => Navigator.of(context).push(
                            MaterialPageRoute(
                                builder: (_) => const Calendar()))),
                    ListTile(
                      leading: const Icon(
                        Icons.palette_outlined,
                        size: 22,
                      ),
                      title: Text('Appearance',
                          style: Theme.of(context).textTheme.labelSmall),
                      onTap: () => Navigator.of(context).push(
                          MaterialPageRoute(builder: (_) => Appearence())),
                    ),
                    ListTile(
                      leading: const Icon(
                        Icons.question_answer_outlined,
                        size: 22,
                      ),
                      title: Text('FAQ',
                          style: Theme.of(context).textTheme.labelSmall),
                      onTap: () => Navigator.of(context).push(
                          MaterialPageRoute(builder: (_) => const faq())),
                    ),
                    ListTile(
                      leading: const Icon(
                        Icons.star_border,
                        size: 22,
                        color: Colors.amber,
                      ),
                      title: Text('Help',
                          style: Theme.of(context).textTheme.labelSmall),
                      onTap: () => {},
                    ),
                  ],
                )),
          ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Welcome to Flutter'),
        ),
        body: const Center(
          child: Text('Hello World'),
        ),
      ),
    );
  }
}

As you can see, the build method gets a bit annoying to read due to the drawer specifically.

My question is, do I keep this as is, or do I extract the drawer into its own function like this:

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      drawer: _getDrawer()
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Welcome to Flutter'),
        ),
        body: const Center(
          child: Text('Hello World'),
        ),
      ),
    );
  }

Widget _getDrawer(){
    SizedBox(
      width: MediaQuery.of(context).size.width * 0.48,
      child: Drawer(
          elevation: 10,
          backgroundColor: Theme.of(context)
              .colorScheme
              .background
              .withOpacity(0.95),
          child: ListView(
            children: [
              ListTile(
                leading: const Icon(
                  Icons.shopping_cart_outlined,
                  size: 22,
                ),
                title: Text('Shop',
                    style: Theme.of(context).textTheme.labelSmall),
                onTap: () => Navigator.of(context).push(
                    MaterialPageRoute(
                        builder: (_) => const marketView())),
              ),
              ListTile(
                leading: const Icon(
                  Icons.timeline_rounded,
                  size: 22,
                ),
                title: Text('To Do',
                    style: Theme.of(context).textTheme.labelSmall),
                onTap: () => Navigator.of(context).push(
                    MaterialPageRoute(
                        builder: (_) => const todo())),
              ),
              ListTile(
                  leading: const Icon(
                    Icons.square,
                    size: 22,
                  ),
                  title: Text('Calendar',
                      style: Theme.of(context).textTheme.labelSmall),
                  onTap: () => Navigator.of(context).push(
                      MaterialPageRoute(
                          builder: (_) => const Calendar()))),
              ListTile(
                leading: const Icon(
                  Icons.palette_outlined,
                  size: 22,
                ),
                title: Text('Appearance',
                    style: Theme.of(context).textTheme.labelSmall),
                onTap: () => Navigator.of(context).push(
                    MaterialPageRoute(builder: (_) => Appearence())),
              ),
              ListTile(
                leading: const Icon(
                  Icons.question_answer_outlined,
                  size: 22,
                ),
                title: Text('FAQ',
                    style: Theme.of(context).textTheme.labelSmall),
                onTap: () => Navigator.of(context).push(
                    MaterialPageRoute(builder: (_) => const faq())),
              ),
              ListTile(
                leading: const Icon(
                  Icons.star_border,
                  size: 22,
                  color: Colors.amber,
                ),
                title: Text('Help',
                    style: Theme.of(context).textTheme.labelSmall),
                onTap: () => {},
              ),
      }
      }

Assuming that _getDrawer() will only be used once, what is the better practice of these two examples?

CodePudding user response:

Firstly, I will suggest checking Widgets vs helper methods .

Separating code-snippet mostly depends on how you are using it. It is not just about just using one or more. You can create variable if the inner widget will never get changed. But if it needs to update based on state, it won't work until you reassign the variable with setState. Helper method is good, it gets called on every build. So it gets updated. But using widget is better option for performance case. Also, it will call only once if it is a stateless widget.

As for the large snippet, It is better to create a separate widget, provide better performance being separate context and makes fast readable.

  • Related