skip to Main Content

I am very new to flutter and dart, but have experience in Typescript and some OOP. I am attempting to dynamically render my Tabs and TabViews from a list.
I keep encountering this error

Methods can’t be invoked in constant expressions.dart(const_eval_method_invocation)

specifically on this line

const TabBarView(
            children:tabInfoList.map((e)=>e.getView()).toList(),

Context

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  static const title = 'appTitle';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: title,
      themeMode: ThemeMode.system,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.green),
        useMaterial3: true,
        iconTheme: IconThemeData(
          size: 40,
        ),
      ),
      home: MyHomePage(title: title),
    );
  }
}

class TabInfoData {
  final Icon icon;
  final Widget view;
  const TabInfoData({required this.icon, required this.view});


  Tab getTab() {
    return Tab(icon:icon);
  }
  Widget getView(){
    return view;
  }
}
List tabInfoList =[
  TabInfoData(icon: Icon(Icons.person), view: Placeholder()),
  TabInfoData(icon: Icon(Icons.person), view: Placeholder()),
  TabInfoData(icon: Icon(Icons.person), view: Placeholder()),
  TabInfoData(icon: Icon(Icons.person), view: Placeholder()),
];

class MyHomePage extends StatelessWidget {
  final String title;
  const MyHomePage({super.key, required this.title, });
  
  // static const List tabInfoList = [
  //   {'name': 'User', 'icon':Icon(Icons.person), 'view':Placeholder()},
  //   {'name': 'Event', 'icon':Icon(Icons.calendar_month), 'view':Placeholder()},
  //   {'name': 'Audition', 'icon':Icon(Icons.music_note), 'view':Placeholder()},
  // ];
  
  @override
  Widget build(BuildContext context) {
    return DefaultTabController (
    length: 3,
    child: Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        leading: Icon(
          Icons.volume_up,
          size: IconTheme.of(context).size),
        title: Text (title,
            style: Theme.of(context).textTheme.headlineLarge,
            ),
        actions: <Widget>[
          IconButton(
            icon: const Icon(Icons.search),
            tooltip: 'Search',
            onPressed: (){},
            padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            iconSize: IconTheme.of(context).size,
          ),
          Padding(
            padding: EdgeInsets.symmetric(horizontal: 10),
          )
        ],
        
      ),
      body: const TabBarView(
            children:tabInfoList.map((e)=>e.getView()).toList(),
),
      bottomNavigationBar: TabBar(
        tabs: <Tab>[
            Tab(icon: Icon(Icons.calendar_month)),
            Tab(icon: Icon(Icons.directions_transit)),
            Tab(icon: Icon(Icons.directions_bike)),
          ],
      ),
    )
    );
  }
}

As you can see from the commented code I have tried putting tabInfoList inside the myHomePage widget as well, no luck.

Does the myHomePage need to have State to fix this? Why, If those things wont change?

my instinct tells me this is a misunderstanding of type or state

2

Answers


  1. Just remove const

    Replace this code :

    body: const TabBarView(
                children:tabInfoList.map((e)=>e.getView()).toList(),),
    

    With :

    body: TabBarView(
            children:tabInfoList.map((e)=>e.getView()).toList(),),
    
    Login or Signup to reply.
  2. const in the JavaScript/TypeScript world means something else than const in the Dart world (or pretty much anywhere else, for that matter).

    In JS/TS, const means that the value of a variable cannot be changed after instantiated, but in Dart, const means a value is known at compile time. This allows for some more aggressive optimization, but it also means that values that can’t be known at compile time (such as the return value of functions/methods) cannot be marked as const.

    Normally, most widgets in Flutter can (and should) be marked as const. But if you want to pass a non-const value as a parameter, that’s not possible. By calling tabInfoList.map within the constructor parameter, you are making the constructor take a non-const value, so you can no longer mark TabVarView as const.

    This means the fix is to simply remove const:

    body: TabBarView(
                children:tabInfoList.map((e)=>e.getView()).toList(),
    
    // Bonus alternative loop syntax:
    
    body: TabBarView(
      children: [
        for (final info in tabInfoList) info.getView(),
      ],
    ),
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search