'Unhandled Exception: type '(Currency?) => Null' is not a subtype of type '(dynamic) => dynamic' [duplicate]
I am trying to add a wrapper around DropdownButton, But I am getting the below exception, I tried calling onChanged property directly in the block body as below
onChanged: (T? newValue) {
widget.onChanged(newValue!);
}
But, it doesn't seem to make any difference.
Launching lib/main.dart on iPhone 12 Pro in debug mode...
lib/main.dart:1
Xcode build done. 28.2s
Connecting to VM Service at ws://127.0.0.1:64267/kXwziwCdk9M=/ws
[VERBOSE-2:ui_dart_state.cc(209)] Unhandled Exception: type '(Currency?) => Null' is not a subtype of type '(dynamic) => dynamic'
#0 _EmDropdownButtonState.build.<anonymous closure>
package:new_app/main.dart:34
#1 _DropdownButtonState._handleTap.<anonymous closure>
package:flutter/…/material/dropdown.dart:1284
#2 _rootRunUnary (dart:async/zone.dart:1434:47)
#3 _CustomZone.runUnary (dart:async/zone.dart:1335:19)
<asynchronous suspension>
Here's the complete code sample
import 'package:flutter/material.dart';
class EmDropdownButton<T> extends StatefulWidget {
final List<T> items;
final Function(T?) onChanged;
final T? value;
final Widget Function(T) dropdownItem;
const EmDropdownButton(
{Key? key,
required this.items,
required this.onChanged,
required this.dropdownItem,
required this.value})
: super(key: key);
@override
State<EmDropdownButton> createState() => _EmDropdownButtonState();
}
class _EmDropdownButtonState<T> extends State<EmDropdownButton<T>> {
@override
Widget build(BuildContext context) {
return DropdownButton<T>(
value: widget.value,
isExpanded: true,
icon: const Icon(Icons.keyboard_arrow_down_rounded),
iconSize: 24,
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (T? newValue) => widget.onChanged(newValue!),
menuMaxHeight: 200,
items: widget.items.map<DropdownMenuItem<T>>((T value) {
return DropdownMenuItem<T>(
value: value, child: widget.dropdownItem(value));
}).toList(),
);
}
}
class Currency {
final String name;
final String symbol;
final String code;
Currency({required this.name, required this.symbol, required this.code});
Currency.init() : this(name: 'Indian Rupee', symbol: '₹', code: 'INR');
@override
bool operator ==(Object other) =>
other is Currency &&
other.name == name &&
other.code == code &&
other.symbol == symbol;
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late Currency currency;
@override
void initState() {
super.initState();
currency = Currency.init();
}
List<Currency> currencyList = [
Currency(code: 'INR', name: 'Indian Rupee', symbol: '₹'),
Currency(code: 'USD', name: 'US Dollar', symbol: '\$'),
Currency(code: 'EUR', name: 'Euro', symbol: '€'),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
SizedBox(
width: 160,
child: EmDropdownButton<Currency>(
value: currency,
dropdownItem: (dynamic x) => Text(x.name),
items: currencyList,
onChanged: (Currency? newValue) {
setState(() {
currency = newValue!;
});
},
),
),
Text(
'_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
);
}
}
The second issue is, If I don't specify dynamic here
dropdownItem: (dynamic x) => Text(x.name),
I get the following exception
Exception has occurred.
_TypeError (type '(Currency) => Text' is not a subtype of type '(dynamic) => Widget')
Solution 1:[1]
I was able to fix the issue by specifying the generic Type to createState
@override
State<EmDropdownButton> createState() => _EmDropdownButtonState();
to
@override
State<EmDropdownButton<T>> createState() => _EmDropdownButtonState();
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Mahesh Jamdade |
