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
Just remove
const
Replace this code :
With :
const
in the JavaScript/TypeScript world means something else thanconst
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 asconst
.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 callingtabInfoList.map
within the constructor parameter, you are making the constructor take a non-const
value, so you can no longer markTabVarView
asconst
.This means the fix is to simply remove
const
: