"Closure call with mismatched arguments", but I can't figure out why - flutter

I'm getting a "Closure call with mismatched arguments"-error when I try to submit a form in my Flutter app, and I don't have a single clue why it's happening. It seems to have issues with my handleInputSave-function, however I'm only calling it once and I've confirmed multiple times that the arguments are correct.
The complete error:
I/flutter ( 6655): ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
I/flutter ( 6655): The following NoSuchMethodError was thrown while handling a gesture:
I/flutter ( 6655): Closure call with mismatched arguments: function '_MetricState.build.<anonymous closure>'
I/flutter ( 6655): Receiver: Closure: (dynamic) => bool
I/flutter ( 6655): Tried calling: _MetricState.build.<anonymous closure>()
I/flutter ( 6655): Found: _MetricState.build.<anonymous closure>(dynamic) => bool
I/flutter ( 6655):
I/flutter ( 6655): When the exception was thrown, this was the stack:
I/flutter ( 6655): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
I/flutter ( 6655): #1 NumberInputState.build.<anonymous closure> (package:greeklibrary/components/Select/Metric/numberinput.dart:60:26)
I/flutter ( 6655): #2 FormFieldState._validate (package:flutter/src/widgets/form.dart)
I/flutter ( 6655): #3 FormFieldState.validate.<anonymous closure> (package:flutter/src/widgets/form.dart:364:7)
I/flutter ( 6655): #4 State.setState (package:flutter/src/widgets/framework.dart:1141:30)
I/flutter ( 6655): #5 FormFieldState.validate (package:flutter/src/widgets/form.dart:363:5)
I/flutter ( 6655): #6 FormState._validate (package:flutter/src/widgets/form.dart:203:25)
I/flutter ( 6655): #7 FormState.validate (package:flutter/src/widgets/form.dart:197:12)
I/flutter ( 6655): #8 _MetricState.build.<anonymous closure> (package:greeklibrary/components/Select/Metric/metric.dart:48:51)
I/flutter ( 6655): #9 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:654:14)
I/flutter ( 6655): #10 _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:729:32)
I/flutter ( 6655): #11 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
I/flutter ( 6655): #12 TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:365:11)
I/flutter ( 6655): #13 TapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:275:7)
I/flutter ( 6655): #14 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:455:9)
I/flutter ( 6655): #15 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:75:13)
I/flutter ( 6655): #16 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:102:11)
I/flutter ( 6655): #17 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:218:19)
I/flutter ( 6655): #18 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:198:22)
I/flutter ( 6655): #19 GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:156:7)
I/flutter ( 6655): #20 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:102:7)
I/flutter ( 6655): #21 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:86:7)
I/flutter ( 6655): #25 _invoke1 (dart:ui/hooks.dart:263:10)
I/flutter ( 6655): #26 _dispatchPointerDataPacket (dart:ui/hooks.dart:172:5)
I/flutter ( 6655): (elided 3 frames from package dart:async)
I/flutter ( 6655):
I/flutter ( 6655): Handler: "onTap"
I/flutter ( 6655): Recognizer:
I/flutter ( 6655): TapGestureRecognizer#8abdf
I/flutter ( 6655): ════════════════════════════════════════════════════════════════════════════════════════════════════
The Metric (parent) widget:
import "package:flutter/material.dart";
import 'package:greeklibrary/styles/variables.dart';
import "./numberinput.dart";
class Metric extends StatefulWidget {
#override
_MetricState createState() => _MetricState();
}
class _MetricState extends State<Metric> {
final _formKey = GlobalKey<FormState>();
var _formData = {};
void handleInputSave(String name, String value) {
print("called");
setState(() => _formData[name] = value);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: colorPrimary,
body: Container(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Center(
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
NumberInput(
name: "book",
defaultValue: "1",
validator: (value) =>
!RegExp(r"^[0-9]$").hasMatch(value) &&
!RegExp(r"^[1-2][0-4]$").hasMatch(value),
onSaved: (String name, String value) =>
handleInputSave(name, value),
),
SizedBox(
height: 20.0,
),
RaisedButton(
child: Text("Ἀγε!"),
onPressed: () {
print(_formKey.currentState.validate());
if (_formKey.currentState.validate()) {
// _formKey.currentState.save();
print("succeeded");
// Navigator.of(context).pushNamed("/loading");
}
})
],
),
),
),
),
);
}
}
The NumberInput (child) widget:
import "package:flutter/material.dart";
class NumberInput extends StatefulWidget {
final String name;
final String defaultValue;
final Function validator;
final Function onSaved;
NumberInput({this.name, this.defaultValue, this.validator, this.onSaved});
#override
NumberInputState createState() => NumberInputState();
}
class NumberInputState extends State<NumberInput> {
String value;
#override
void initState() {
super.initState();
setState(() => value = widget.defaultValue);
print(widget.onSaved);
}
Widget build(BuildContext context) {
return Row(
children: <Widget>[
ButtonTheme(
minWidth: 14.0,
buttonColor: Color.fromRGBO(0, 0, 0, 0.0),
child: RaisedButton(
child: Text(
"-",
style: TextStyle(fontSize: 32.0),
),
elevation: 1,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
onPressed: () {
setState(() {
if (int.parse(value) > 1) {
value = (int.parse(value) - 1).toString();
}
});
},
),
),
SizedBox(
width: 16.0,
),
Flexible(
child: TextFormField(
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: "Vul een boeknummer in",
),
controller: TextEditingController(text: value),
validator: (value) {
if (widget.validator()) {
return "Vul alstublieft een (geldig) booknummer in.";
}
return null;
},
onSaved: (value) {
widget.onSaved(widget.name, value);
},
),
),
SizedBox(
width: 16.0,
),
ButtonTheme(
minWidth: 14.0,
buttonColor: Color.fromRGBO(0, 0, 0, 0.0),
child: RaisedButton(
child: Text(
"+",
style: TextStyle(fontSize: 32.0),
),
elevation: 1,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
onPressed: () {
setState(() => value = (int.parse(value) + 1).toString());
},
),
),
],
);
}
}

You forgot to put value as parameter for your validator
You can copy paste run full code below
code snippet
if (widget.validator(value)) {
return "Vul alstublieft een (geldig) booknummer in.";
}
demo
full code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
#override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(flex:1, child: Metric()),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
class Metric extends StatefulWidget {
#override
_MetricState createState() => _MetricState();
}
class _MetricState extends State<Metric> {
final _formKey = GlobalKey<FormState>();
var _formData = {};
void handleInputSave(String name, String value) {
print("called");
setState(() => _formData[name] = value);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,//colorPrimary,
body: Container(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Center(
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
NumberInput(
name: "book",
defaultValue: "1",
validator: (value) =>
!RegExp(r"^[0-9]$").hasMatch(value) &&
!RegExp(r"^[1-2][0-4]$").hasMatch(value),
onSaved: (String name, String value) =>
handleInputSave(name, value),
),
SizedBox(
height: 20.0,
),
RaisedButton(
child: Text("Ἀγε!"),
onPressed: () {
print(_formKey.currentState.validate());
if (_formKey.currentState.validate()) {
// _formKey.currentState.save();
print("succeeded");
// Navigator.of(context).pushNamed("/loading");
}
})
],
),
),
),
),
);
}
}
class NumberInput extends StatefulWidget {
final String name;
final String defaultValue;
final Function validator;
final Function onSaved;
NumberInput({this.name, this.defaultValue, this.validator, this.onSaved});
#override
NumberInputState createState() => NumberInputState();
}
class NumberInputState extends State<NumberInput> {
String value;
#override
void initState() {
super.initState();
setState(() => value = widget.defaultValue);
print(widget.onSaved);
}
Widget build(BuildContext context) {
return Row(
children: <Widget>[
ButtonTheme(
minWidth: 14.0,
buttonColor: Color.fromRGBO(0, 0, 0, 0.0),
child: RaisedButton(
child: Text(
"-",
style: TextStyle(fontSize: 32.0),
),
elevation: 1,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
onPressed: () {
setState(() {
if (int.parse(value) > 1) {
value = (int.parse(value) - 1).toString();
}
});
},
),
),
SizedBox(
width: 16.0,
),
Flexible(
child: TextFormField(
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: "Vul een boeknummer in",
),
controller: TextEditingController(text: value),
validator: (value) {
if (widget.validator(value)) {
return "Vul alstublieft een (geldig) booknummer in.";
}
return null;
},
onSaved: (value) {
widget.onSaved(widget.name, value);
},
),
),
SizedBox(
width: 16.0,
),
ButtonTheme(
minWidth: 14.0,
buttonColor: Color.fromRGBO(0, 0, 0, 0.0),
child: RaisedButton(
child: Text(
"+",
style: TextStyle(fontSize: 32.0),
),
elevation: 1,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
onPressed: () {
setState(() => value = (int.parse(value) + 1).toString());
},
),
),
],
);
}
}

Related

data are showing as null when i try to retrieve from firestore - flutter

am building a drawer menu, the drawer is a stateful class i created called "NavigationDrawer"
and it contains user's name and email. The name and email should be retrieved from the cloud firestore as follow:
import 'package:athaddakapp/model/user_model.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class NavigationDrawer extends StatefulWidget {
const NavigationDrawer({Key? key}) : super(key: key);
#override
State<NavigationDrawer> createState() => _NavigationDrawerState();
}
class _NavigationDrawerState extends State<NavigationDrawer> {
User? user = FirebaseAuth.instance.currentUser;
UserModel loggedInUser = UserModel();
#override
void initState() {
super.initState();
FirebaseFirestore.instance
.collection("Users")
.doc(user!.uid)
.get()
.then((value) => this.loggedInUser = UserModel.fromMap(value.data()));
setState(() {});
}
#override
Widget build(BuildContext context) {
return Drawer(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
buildHeader(context),
buildMenuItems(context),
],
),
),
);
}
Widget buildHeader(BuildContext context) => Container(
color: Colors.purple,
padding: EdgeInsets.only(
top: MediaQuery.of(context).padding.top,
),
child: Column(
children: [
CircleAvatar(
radius: 52,
backgroundImage: AssetImage("assets/DefaultImage.png"),
),
SizedBox(height: 12),
Text(
"${loggedInUser.name}",
style: TextStyle(fontSize: 20, color: Colors.white),
),
Text("${loggedInUser.email}",
style: TextStyle(fontSize: 17, color: Colors.white)),
SizedBox(
height: 12,
)
],
),
);
Widget buildMenuItems(BuildContext context) => Container(
padding: EdgeInsets.all(20),
child: Wrap(
runSpacing: 14,
children: [
ListTile(
trailing: Icon(Icons.home_outlined),
title: Text(
'الصفحة الرئيسية',
textAlign: TextAlign.right,
),
onTap: () {},
),
ListTile(
trailing: Icon(Icons.flag_outlined),
title: Text(
"تحدياتي",
textAlign: TextAlign.right,
),
onTap: () {},
),
ListTile(
trailing: Icon(Icons.flag_circle_outlined),
title: Text(
'جميع التحديات',
textAlign: TextAlign.right,
),
onTap: () {},
),
ListTile(
trailing: Icon(Icons.settings_outlined),
title: Text(
'إعدادات الحساب',
textAlign: TextAlign.right,
),
onTap: () {},
),
Divider(
color: Colors.purple,
),
ListTile(
trailing: Icon(Icons.question_mark_outlined),
title: Text(
'عن التطبيق',
textAlign: TextAlign.right,
),
onTap: () {},
),
ListTile(
trailing: Icon(Icons.phone_outlined),
title: Text(
'اتصل بنا',
textAlign: TextAlign.right,
),
onTap: () {},
)
],
),
);
}
this navigation class is invoked in other screen called "home_screen", the values are showing as "null" i made sure about the collection name and i restarted the app multiple times but the values still showing as null. i also imported the necessary libraries, here is the firestore database:
when i open the drawer for the first time i logged debugger shows this error:
E/flutter ( 4873): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: NoSuchMethodError: The method '[]' was called on null.
E/flutter ( 4873): Receiver: null
E/flutter ( 4873): Tried calling: []("uid")
E/flutter ( 4873): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:38:5)
E/flutter ( 4873): #1 new UserModel.fromMap
package:athaddakapp/model/user_model.dart:24
E/flutter ( 4873): #2 _NavigationDrawerState.initState.<anonymous closure>
package:athaddakapp/screens/navigation_drawer.dart:26
E/flutter ( 4873): #3 _rootRunUnary (dart:async/zone.dart:1434:47)
E/flutter ( 4873): #4 _CustomZone.runUnary (dart:async/zone.dart:1335:19)
E/flutter ( 4873): <asynchronous suspension>
E/flutter ( 4873):
Move setState to inside of then()... something like:
#override
void initState() {
super.initState();
FirebaseFirestore.instance
.collection("Users")
.doc(user!.uid)
.get()
.then((value) => setState(() => this.loggedInUser = UserModel.fromMap(value.data())));
}

Converting Lat Lng to Address displays null in flutter?

The function displays the location Location NULL. I am getting the current location in superinit state and want to display the address from the placemark as text in the size box widget.
The function I have created to convert latitude and longitude to address getAdd() is also initialized in the initial state but when I call placemark in the text widget it displays null.
I have entered dummy values as well and tried printing in debug console which says.
E/flutter (29935): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: PlatformException(IO_ERROR, A network error occurred trying to lookup the supplied coordinates (*******************, *******************)., null, null)
E/flutter (29935): #0 StandardMethodCodec.decodeEnvelope
package:flutter/…/services/message_codecs.dart:597
E/flutter (29935): #1 MethodChannel._invokeMethod
package:flutter/…/services/platform_channel.dart:158
E/flutter (29935): <asynchronous suspension>
E/flutter (29935): #2 MethodChannelGeocoding.placemarkFromCoordinates
package:geocoding_platform_interface/…/implementations/method_channel_geocoding.dart:56
E/flutter (29935): <asynchronous suspension>
E/flutter (29935): #3 _MapState.getAdd
package:donation_yoga/screens/maps.dart:32
E/flutter (29935): <asynchronous suspension>
E/flutter (29935):
The Map class is the following
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:geocoding/geocoding.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import 'AddData.dart';
class Map extends StatefulWidget {
#override
State<StatefulWidget> createState() => _MapState();
}
class _MapState extends State<Map> {
Position curLoc;
bool mapToggle = false;
GoogleMapController mapController;
List<Placemark> placemarks;
void initState() {
super.initState();
Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.best)
.then((curL) => {
setState(() {
curLoc = curL;
mapToggle = true;
}),
});
getAdd();
}
getAdd() async {
placemarks = await placemarkFromCoordinates(52.2165157, 6.9437819);
print(placemarks);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
myLayoutWidget(),
_createForm(context),
Align(
alignment: Alignment.topCenter,
child: SizedBox(
width: 200.0,
height: 100.0,
child: Card(
color: Colors.green,
child: Center(
child: Text(
"Location $placemarks",
style: TextStyle(color: Colors.white),
), //Text
), //Center
), //Card
),
),
],
),
);
}
Widget myLayoutWidget() {
return Container(
child: mapToggle
? GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(curLoc.latitude, curLoc.longitude),
zoom: 15.0),
myLocationButtonEnabled: true,
zoomGesturesEnabled: true,
)
: Center(
child: Text(
'Getting Location Please Wait.....',
style: TextStyle(fontSize: 20.0),
),
));
}
Widget _createForm(BuildContext context) {
return Align(
alignment: Alignment.bottomLeft,
child: FloatingActionButton(
backgroundColor: Colors.green,
child: const Icon(Icons.create),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => AddData()),
);
},
),
);
}
}

the following NoSuchMethodError was thrown building QuizPage(dirty, state: _QuizPageState#307d6): The getter 'length' was called on null [duplicate]

This question already has answers here:
What is a NoSuchMethod error and how do I fix it?
(2 answers)
Closed 2 years ago.
i am developing a flutter quiz. Error:
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building QuizPage (dirty, state: _QuizPageState # 307d6):
The getter 'length' was called on null.
Receiver: null
Tried calling: length
error https://pastebin.com/8JCG7Ecj https://pastebin.com/s0kvXLr1
after a few seconds the application is executed
But I got an exception, where I know where the exception and what it means, but i do not have any clue how i could solve the problem. I hope some of you guys could help me.
Git: https://github.com/ivsongborges/app_g6pd.git
class QuizPage extends StatefulWidget {
#override
_QuizPageState createState() => _QuizPageState();
}
class _QuizPageState extends State<QuizPage> {
final _controller = QuizController();
List<Widget> _scoreKeeper = [];
bool _loading = true;
#override
void initState() {
super.initState();
_initialize();
}
Future<void> _initialize() async {
await _controller.initialize();
setState(() {
_loading = false;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue,
title: Text('QUIZ G6PD ( ${_scoreKeeper.length}/${_controller.questionsNumber} )'),
centerTitle: true,
elevation: 0.0,
),
backgroundColor: Colors.white,
body: SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0),
child: _buildQuiz(),
),
),
);
}
_buildQuiz() {
if (_loading) return CenteredCircularProgress();
if (_controller.questionsNumber == 0)
return CenteredMessage(
'Sem questões',
icon: Icons.warning,
);
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
_buildQuestion(_controller.getQuestion()),
_buildAnswerButton(_controller.getAnswer1()),
_buildAnswerButton(_controller.getAnswer2()),
_buildScoreKeeper(),
],
);
}
_buildQuestion(String question) {
return Expanded(
flex: 5,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: Center(
child: Text(
question,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25.0,
color: Colors.black,
),
),
),
),
);
}
_buildAnswerButton(String answer) {
return Expanded(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: GestureDetector(
child: Container(
padding: EdgeInsets.all(4.0),
color: Colors.blue,
child: Center(
child: AutoSizeText(
answer,
maxLines: 2,
minFontSize: 10.0,
maxFontSize: 32.0,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
),
),
),
),
onTap: () {
bool correct = _controller.correctAnswer(answer);
ResultDialog.show(
context,
question: _controller.question,
correct: correct,
onNext: () {
setState(() {
_scoreKeeper.add(
Icon(
correct ? Icons.check : Icons.close,
color: correct ? Colors.green : Colors.red,
),
);
if (_scoreKeeper.length < _controller.questionsNumber) {
_controller.nextQuestion();
} else {
FinishDialog.show(
context,
hitNumber: _controller.hitNumber,
questionNumber: _controller.questionsNumber
);
}
});
},
);
},
),
),
);
}
_buildScoreKeeper() {
return Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: _scoreKeeper,
),
);
}
}
The error message in the link states something else:
I/flutter (26474): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (26474): The following NoSuchMethodError was thrown building QuizPage(dirty, state: _QuizPageState#d376a):
I/flutter (26474): The getter 'length' was called on null.
I/flutter (26474): Receiver: null
I/flutter (26474): Tried calling: length
I/flutter (26474):
I/flutter (26474): The relevant error-causing widget was:
I/flutter (26474): QuizPage file:///C:/Users/ivs_g/AndroidStudioProjects/dog/flutter_app/lib/pages/home.page.dart:26:43
I/flutter (26474):
I/flutter (26474): When the exception was thrown, this was the stack:
I/flutter (26474): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
I/flutter (26474): #1 QuizController.questionsNumber (package:flutter_app/controllers/quiz_controller.dart:13:44)
I/flutter (26474): #2 _QuizPageState.build (package:flutter_app/pages/quiz.page.dart:39:71)
I/flutter (26474): #3 StatefulElement.build (package:flutter/src/widgets/framework.dart:4663:28)
I/flutter (26474): #4 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4546:15)
I/flutter (26474): #5 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4719:11)
I/flutter (26474): #6 Element.rebuild (package:flutter/src/widgets/framework.dart:4262:5)
I/flutter (26474): #7 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4525:5)
It is clear that the last called method is QuizController.questionNumber hence, the problem is _contoller.questionNumber
The problem is either that _controller hasn't been declared properly. It should be final QuizController _controller = QuizController();
or there is an error inside QuizController()
For a more comprehensive answer check out What is a NoSuchMethod error and how do I fix it?

Flutter - Unhandled Exception: setState() called after dispose()

I tried to make a compass for a flutter app.
This idea was to put an image of the compass on the camera preview.
The result seems to be ok:
First, the user has a camera preview with the compass :
The name of the room can be added.
When the user takes a picture, it makes a screenshot that can be shared:
Even it seems to work fine, I have the following error message on Android Studio:
E/flutter (29454): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: setState() called after dispose(): _CompassState#46249(lifecycle state: defunct, not mounted)
E/flutter (29454): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
E/flutter (29454): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
E/flutter (29454): This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
E/flutter (29454): #0 State.setState.<anonymous closure> (package:flutter/src/widgets/framework.dart:1204:9)
E/flutter (29454): #1 State.setState (package:flutter/src/widgets/framework.dart:1239:6)
E/flutter (29454): #2 _CompassState._onData (package:franck_ehrhart/seller/compass.dart:28:29)
E/flutter (29454): #3 _rootRunUnary (dart:async/zone.dart:1198:47)
E/flutter (29454): #4 _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter (29454): #5 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
E/flutter (29454): #6 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:357:11)
E/flutter (29454): #7 _DelayedData.perform (dart:async/stream_impl.dart:611:14)
E/flutter (29454): #8 _StreamImplEvents.handleNext (dart:async/stream_impl.dart:730:11)
E/flutter (29454): #9 _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:687:7)
E/flutter (29454): #10 _rootRun (dart:async/zone.dart:1182:47)
E/flutter (29454): #11 _CustomZone.run (dart:async/zone.dart:1093:19)
E/flutter (29454): #12 _CustomZone.runGuarded (dart:async/zone.dart:997:7)
E/flutter (29454): #13 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1037:23)
E/flutter (29454): #14 _rootRun (dart:async/zone.dart:1190:13)
E/flutter (29454): #15 _CustomZone.run (dart:async/zone.dart:1093:19)
E/flutter (29454): #16 _CustomZone.runGuarded (dart:async/zone.dart:997:7)
E/flutter (29454): #17 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1037:23)
E/flutter (29454): #18 _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter (29454): #19 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
E/flutter (29454):
Here is the source code for the compass:
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_compass/flutter_compass.dart';
class Compass extends StatefulWidget {
Compass({Key key}) : super(key: key);
#override
_CompassState createState() => _CompassState();
}
class _CompassState extends State<Compass> {
double _heading = 0;
String get _readout => _heading.toStringAsFixed(0) + '°';
#override
void initState() {
super.initState();
FlutterCompass.events.listen(_onData);
}
void _onData(double x) => setState(() { _heading = x; });
final TextStyle _style = TextStyle(
color: Colors.red,
fontSize: 32,
fontWeight: FontWeight.bold,
backgroundColor: Colors.white.withOpacity(0.5) ,
);
#override
Widget build(BuildContext context) {
return CustomPaint(
foregroundPainter: CompassPainter(angle: _heading),
child: Center(child: Text(_readout, style: _style))
);
}
}
class CompassPainter extends CustomPainter {
CompassPainter({ #required this.angle }) : super();
final double angle;
double get rotation => -2 * pi * (angle / 360);
Paint get _brush => new Paint()
..style = PaintingStyle.stroke
..strokeWidth = 4.0;
#override
void paint(Canvas canvas, Size size) {
Paint circle = _brush
..color = Colors.blue.shade800.withOpacity(0.6);
Paint needle = _brush
..color = Colors.lightBlueAccent;
double radius = min(size.width / 2.2, size.height / 2.2);
Offset center = Offset(size.width / 2, size.height / 2);
Offset start = Offset.lerp(Offset(center.dx, radius), center, .4);
Offset end = Offset.lerp(Offset(center.dx, radius), center, -2);
canvas.translate(center.dx, center.dy);
canvas.rotate(rotation);
canvas.translate(-center.dx, -center.dy);
canvas.drawLine(start, end, needle);
canvas.drawCircle(center, radius, circle);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
Here is the code for the page displaying both camera preview and compass:
import 'package:camera/camera.dart';
import 'package:flutter/cupertino.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart';
import'package:franck_ehrhart/camera/preview_compass.dart';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/rendering.dart';
import 'package:image_picker_saver/image_picker_saver.dart';
import 'package:flutter/services.dart';
class CompassTool extends StatefulWidget {
// Screenshot
CompassTool({Key key}) : super(key: key);
#override
_CompassToolState createState() => _CompassToolState();
}
class _CompassToolState extends State<CompassTool> {
// Screenshot
static GlobalKey screen = new GlobalKey();
// Camera
CameraController controller;
List cameras;
int selectedCameraIndex;
String imgPath;
String compassPath;
// Textinput name of room
TextEditingController nameController = TextEditingController();
String roomName = '';
#override
void initState() {
super.initState();
// Camera
availableCameras().then((availableCameras) {
cameras = availableCameras;
if (cameras.length > 0) {
setState(() {
selectedCameraIndex = 0;
});
_initCameraController(cameras[selectedCameraIndex]).then((void v) {});
} else {
print('No camera available');
}
}).catchError((err) {
print('Error :${err.code}Error message : ${err.message}');
});
}
Future _initCameraController(CameraDescription cameraDescription) async {
if (controller != null) {
await controller.dispose();
}
controller = CameraController(cameraDescription, ResolutionPreset.medium);
controller.addListener(() {
if (mounted) {
setState(() {});
}
if (controller.value.hasError) {
print('Camera error ${controller.value.errorDescription}');
}
});
try {
await controller.initialize();
} on CameraException catch (e) {
_showCameraException(e);
}
if (mounted) {
setState(() {});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blueAccent,
appBar: AppBar(
title: Text("ORIENTATION PIECES"),
centerTitle: true,
backgroundColor: Colors.blueAccent.shade700,
),
// body: Compass()
body:
Container(
child: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
flex: 1,
child:
_cameraPreviewWidget(),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: 80,
width: double.infinity,
padding: EdgeInsets.all(15),
color: Colors.blueAccent,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
_cameraToggleRowWidget(),
_cameraControlWidget(context),
Spacer()
],
),
),
),
Card(
margin: EdgeInsets.symmetric( horizontal: 10.0, vertical :5.0),
child: TextField(
controller: nameController,
decoration: InputDecoration(
hintText: 'Nom de la pièce',
border: OutlineInputBorder(),
labelText: 'Nom de la pièce',
),
onChanged: (text) {
setState(() {
roomName = text;
//you can access nameController in its scope to get
// the value of text entered as shown below
//fullName = nameController.text;
}
);
},
),
),
]
),
),
),
);
}
/// Display the control bar with buttons to take pictures
Widget _cameraControlWidget(context) {
return Expanded(
child: Align(
alignment: Alignment.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
FloatingActionButton(
child: Icon(
Icons.camera,
color: Colors.black,
),
backgroundColor: Colors.white,
onPressed: () {
_onCapturePressed(context);
},
),
],
),
),
);
}
/// Display Camera preview.
Widget _cameraPreviewWidget() {
if (controller == null || !controller.value.isInitialized) {
return const Text(
'Loading',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.w900,
),
);
}
return
//screenshot
RepaintBoundary(
key: screen,
child: Stack(
alignment: FractionalOffset.center,
children: <Widget>[
new Positioned.fill(
child: new AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: new CameraPreview(controller)),
),
new Positioned.fill(
child: Compass(
)
),
],
),
);
}
/// Display a row of toggle to select the camera (or a message if no camera is available).
Widget _cameraToggleRowWidget() {
if (cameras == null || cameras.isEmpty) {
return Spacer();
}
CameraDescription selectedCamera = cameras[selectedCameraIndex];
CameraLensDirection lensDirection = selectedCamera.lensDirection;
return Expanded(
child: Align(
alignment: Alignment.centerLeft,
child: FlatButton.icon(
onPressed: _onSwitchCamera,
icon: Icon(
_getCameraLensIcon(lensDirection),
color: Colors.white,
size: 24,
),
label: Text(
'${lensDirection.toString().substring(lensDirection.toString().indexOf('.') + 1).toUpperCase()}',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500
),),
),
),
);
}
// Camera
IconData _getCameraLensIcon(CameraLensDirection direction) {
switch (direction) {
case CameraLensDirection.back:
return CupertinoIcons.switch_camera;
case CameraLensDirection.front:
return CupertinoIcons.switch_camera_solid;
case CameraLensDirection.external:
return Icons.camera;
default:
return Icons.device_unknown;
}
}
void _showCameraException(CameraException e) {
String errorText = 'Error:${e.code}\nError message : ${e.description}';
print(errorText);
}
void _onCapturePressed(context) async {
try {
// Compass
RenderRepaintBoundary boundary = screen.currentContext.findRenderObject();
ui.Image image = await boundary.toImage();
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
final compassPath =
await ImagePickerSaver.saveFile(
fileData:byteData.buffer.asUint8List() );
// Camera
final path =
join((await getTemporaryDirectory()).path, '${DateTime.now()}.png');
await controller.takePicture(path);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PreviewCompass(
imgPath: path,
compassPath: compassPath,
roomName: roomName,
)
),
);
} catch (e) {
_showCameraException(e);
}
}
void _onSwitchCamera() {
selectedCameraIndex =
selectedCameraIndex < cameras.length - 1 ? selectedCameraIndex + 1 : 0;
CameraDescription selectedCamera = cameras[selectedCameraIndex];
_initCameraController(selectedCamera);
}
}
And here is the code for the page displaying the screenshot of the previous screen:
import 'dart:io';
import 'dart:typed_data';
import 'package:esys_flutter_share/esys_flutter_share.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
// packages screenshot
import 'package:flutter/rendering.dart';
import 'package:screenshot/screenshot.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_icons/flutter_icons.dart';
// Compass
class PreviewCompass extends StatefulWidget{
final String imgPath;
final String compassPath;
final String roomName;
const PreviewCompass({Key key, this.imgPath, this.compassPath, this.roomName}) : super(key: key);
//PreviewCompass({this.imgPath,this.roomName});
#override
_PreviewCompassState createState() => _PreviewCompassState();
}
class _PreviewCompassState extends State<PreviewCompass>{
// Screenshot
File _imageFile;
ScreenshotController screenshotController = ScreenshotController();
#override
Widget build(BuildContext context) {
return Screenshot(
controller: screenshotController,
child:
Scaffold(
backgroundColor: Colors.blueAccent,
appBar: AppBar(
automaticallyImplyLeading: true,
title: Text("ORIENTATION PIECE"),
centerTitle: true,
backgroundColor: Colors.blueAccent.shade700,
),
body: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
flex: 2,
child: Stack(
alignment: FractionalOffset.center,
children: <Widget>[
new Positioned.fill(child:
Image.file(File(widget.imgPath),fit: BoxFit.fill,),),
new Positioned.fill(child:
Image.file(File(widget.compassPath),fit: BoxFit.fill,),),
/*
Expanded(
// flex: 1,
child:
Image.file(File(widget.imgPath),fit: BoxFit.fill,),
),
Align(
// alignment: Alignment.bottomCenter,
child: Image.file(File(widget.compassPath),fit: BoxFit.fill,),
),*/
],
),
),
Card(
margin: EdgeInsets.symmetric( horizontal: 10.0, vertical :5.0),
child: ListTile (
leading: Icon(
FontAwesome.compass,
color: Colors.blue.shade900,
),
title: (
Text (widget?.roomName,
style: TextStyle(
fontSize: 15.0,
fontFamily: 'Source Sans Pro',
color: Colors.blue.shade900,
)
)
),
)
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
width: double.infinity,
height: 60.0,
color: Colors.black,
child: Center(
child: IconButton(
icon: Icon(Icons.share,color: Colors.white,),
onPressed: () async {
_takeScreenshotandShare();
},
),
),
),
),
],
),
),
),
);
}
// Screenshot
_takeScreenshotandShare() async {
_imageFile = null;
screenshotController
.capture(delay: Duration(milliseconds: 10), pixelRatio: 2.0)
.then((File image) async {
setState(() {
_imageFile = image;
});
final directory = (await getApplicationDocumentsDirectory()).path;
Uint8List pngBytes = _imageFile.readAsBytesSync();
File imgFile = new File('$directory/screenshot.png');
imgFile.writeAsBytes(pngBytes);
print("File Saved to Gallery");
await Share.file('Screenshot', 'screenshot.png', pngBytes, 'image/png');
})
.catchError((onError) {
print(onError);
});
}
}
Can you please help me with this error ?
Many thanks.
Your error comes from here:
FlutterCompass.events.listen(_onData);
You should store that stream subscription in a variable and cancel it in the dispose method:
StreamSubscription<double> stream;
#override
void initState() {
super.initState();
stream = FlutterCompass.events.listen(_onData);
}
#override
void dispose() {
stream.cancel();
super.dispose();
}

type '() => Null' is not a subtype of type '(TapDownDetails) => void'

I am practicing a BMI app. I have completed everything, currently i am abstracting my code. I have created a class called ReusableAgeWeightCard and i have inserted function over there onTapDownMinus, onTapUp, onTapCancel, onPressMinus, onTapDownPlus, onPressPlus. I don't know what error i have made with the TapDownDetails details?
class ReusableAgeWeightCard extends StatelessWidget {
final Widget changeMode;
final String label;
final String unit;
final int si;
final Function onTapDownMinus;
final Function onTapUp;
final Function onTapCancel;
final Function onPressMinus;
final Function onTapDownPlus;
final Function onPressPlus;
ReusableAgeWeightCard({
#required this.label,
this.changeMode,
this.unit,
#required this.si,
#required this.onTapDownMinus,
#required this.onTapUp,
#required this.onTapCancel,
#required this.onPressMinus,
#required this.onTapDownPlus,
#required this.onPressPlus,
});
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(6.0),
margin: EdgeInsets.all(15.0),
decoration: BoxDecoration(
color: kActiveCardColor,
borderRadius: BorderRadius.circular(15.0),
),
child: Stack(
alignment: Alignment.topRight,
children: <Widget>[
changeMode,
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(
label,
style: kLabelTextStyle,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: <Widget>[
Text(
si.toString(),
style: kNumberMediumTextStyle,
),
Text(
unit,
style: kLabelTextStyle,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTapDown: onTapDownMinus,
onTapUp: onTapUp,
onTapCancel: onTapCancel,
onTap: onPressMinus,
child: RawMaterialButton(
elevation: 6.0,
fillColor: Color(0xff4c4f5e),
shape: CircleBorder(),
constraints: BoxConstraints.tightFor(
height: 56.0,
width: 56.0,
),
child: Icon(
FontAwesomeIcons.minus,
size: 25.0,
color: Colors.white,
),
),
),
SizedBox(
width: 10.0,
),
GestureDetector(
onTapDown: onTapDownPlus,
onTapUp: onTapUp,
onTapCancel: onTapCancel,
onTap: onPressPlus,
child: RawMaterialButton(
elevation: 6.0,
fillColor: Color(0xff4c4f5e),
shape: CircleBorder(),
constraints: BoxConstraints.tightFor(
height: 56.0,
width: 56.0,
),
child: Icon(
FontAwesomeIcons.plus,
size: 25.0,
color: Colors.white,
),
),
),
],
)
],
),
],
),
);
}
}
ReusableAgeWeightCard(
label: 'AGE',
unit: '',
si: age,
onTapDownMinus: (TapDownDetails details) {
minusOnTapDown('age');
},
onTapUp: (TapUpDetails details) {
cancelTimer();
},
onTapCancel: () {
cancelTimer();
},
onPressMinus: () {
minusOnPress('age');
},
onTapDownPlus: () {
plusOnTapDown('age');
},
onPressPlus: () {
plusOnPress('age');
}),
This is the function
void minusOnTapDown(String parameter) {
if (parameter == 'age') {
timer = Timer.periodic(Duration(milliseconds: 100), (timer) {
setState(() {
age--;
if (age <= 1) {
timer.cancel();
age = 1;
}
});
});
} else if (parameter == 'pound') {
timer = Timer.periodic(Duration(milliseconds: 100), (timer) {
setState(() {
pound--;
if (pound <= 1) {
timer.cancel();
pound = 1;
}
});
});
} else {
timer = Timer.periodic(Duration(milliseconds: 100), (timer) {
setState(() {
kg--;
if (kg <= 1) {
timer.cancel();
kg = 1;
}
});
});
}
}
void plusOnTapDown(String parameter) {
if (parameter == 'age') {
timer = Timer.periodic(Duration(milliseconds: 100), (timer) {
setState(() {
age++;
if (age > 117) {
timer.cancel();
age = 117;
}
});
});
} else if (parameter == 'pound') {
timer = Timer.periodic(Duration(milliseconds: 100), (timer) {
setState(() {
pound++;
if (pound >= 450) {
timer.cancel();
}
});
});
} else {
timer = Timer.periodic(Duration(milliseconds: 100), (timer) {
setState(() {
kg++;
if (kg >= 204) {
timer.cancel();
kg = 204;
}
});
});
}
}
void cancelTimer() {
setState(() {
timer.cancel();
});
}
void minusOnPress(String parameter) {
if (parameter == 'age') {
setState(() {
age--;
if (age <= 1) {
age = 1;
}
});
} else if (parameter == 'pound') {
setState(() {
pound--;
if (pound <= 1) {
pound = 1;
}
});
} else {
setState(() {
kg--;
if (kg <= 1) {
kg = 1;
}
});
}
}
void plusOnPress(String parameter) {
if (parameter == 'age') {
setState(() {
age++;
if (age >= 117) {
age = 117;
}
});
} else if (parameter == 'pound') {
setState(() {
pound++;
if (pound >= 450) {
pound = 450;
}
});
} else {
setState(() {
kg++;
if (kg >= 204) {
kg = 204;
}
});
}
}
This is the error
Performing hot restart...
Syncing files to device Android SDK built for x86...
Restarted application in 3,474ms.
I/flutter ( 2903): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 2903): The following _TypeError was thrown building ReusableAgeWeightCard(dirty):
I/flutter ( 2903): type '() => Null' is not a subtype of type '(TapDownDetails) => void'
I/flutter ( 2903):
I/flutter ( 2903): The relevant error-causing widget was:
I/flutter ( 2903): ReusableAgeWeightCard file:///D:/Other/App/Flutter/bmi/lib/screen/input_page.dart:420:26
I/flutter ( 2903):
I/flutter ( 2903): When the exception was thrown, this was the stack:
I/flutter ( 2903): #0 ReusableAgeWeightCard.build (package:bmi/components/reusable_age_weight_card.dart:92:32)
I/flutter ( 2903): #1 StatelessElement.build (package:flutter/src/widgets/framework.dart:4576:28)
I/flutter ( 2903): #2 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4502:15)
I/flutter ( 2903): #3 Element.rebuild (package:flutter/src/widgets/framework.dart:4218:5)
I/flutter ( 2903): #4 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4481:5)
I/flutter ( 2903): #5 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4476:5)
I/flutter ( 2903): ... Normal element mounting (7 frames)
I/flutter ( 2903): #12 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14)
I/flutter ( 2903): #13 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5947:32)
I/flutter ( 2903): ... Normal element mounting (7 frames)
I/flutter ( 2903): #20 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14)
I/flutter ( 2903): #21 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5947:32)
I/flutter ( 2903): ... Normal element mounting (19 frames)
I/flutter ( 2903): #40 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14)
I/flutter ( 2903): #41 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5947:32)
I/flutter ( 2903): ... Normal element mounting (193 frames)
I/flutter ( 2903): #234 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14)
I/flutter ( 2903): #235 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5947:32)
I/flutter ( 2903): ... Normal element mounting (238 frames)
I/flutter ( 2903): #473 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14)
I/flutter ( 2903): #474 Element.updateChild (package:flutter/src/widgets/framework.dart:3214:18)
I/flutter ( 2903): #475 RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1148:16)
I/flutter ( 2903): #476 RenderObjectToWidgetElement.mount (package:flutter/src/widgets/binding.dart:1119:5)
I/flutter ( 2903): #477 RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> (package:flutter/src/widgets/binding.dart:1061:17)
I/flutter ( 2903): #478 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2607:19)
I/flutter ( 2903): #479 RenderObjectToWidgetAdapter.attachToRenderTree (package:flutter/src/widgets/binding.dart:1060:13)
I/flutter ( 2903): #480 WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:941:7)
I/flutter ( 2903): #481 WidgetsBinding.scheduleAttachRootWidget.<anonymous closure> (package:flutter/src/widgets/binding.dart:922:7)
I/flutter ( 2903): (elided 11 frames from class _RawReceivePortImpl, class _Timer, dart:async, and dart:async-patch)
I/flutter ( 2903):
I/flutter ( 2903): ════════════════════════════════════════════════════════════════════════════════════════════════════
I/flutter ( 2903): Another exception was thrown: type '() => Null' is not a subtype of type '(TapDownDetails) => void'
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following _TypeError was thrown building ReusableAgeWeightCard(dirty):
type '() => Null' is not a subtype of type '(TapDownDetails) => void'
The relevant error-causing widget was:
ReusableAgeWeightCard file:///D:/Other/App/Flutter/bmi/lib/screen/input_page.dart:420:26
When the exception was thrown, this was the stack:
#0 ReusableAgeWeightCard.build (package:bmi/components/reusable_age_weight_card.dart:92:32)
#1 StatelessElement.build (package:flutter/src/widgets/framework.dart:4576:28)
#2 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4502:15)
#3 Element.rebuild (package:flutter/src/widgets/framework.dart:4218:5)
#4 StatelessElement.update (package:flutter/src/widgets/framework.dart:4583:5)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
type '() => Null' is not a subtype of type '(TapDownDetails) => void'
The relevant error-causing widget was:
ReusableAgeWeightCard file:///D:/Other/App/Flutter/bmi/lib/screen/input_page.dart:487:32
════════════════════════════════════════════════════════════════════════════════════════════════════
The function you're passing to GestureDetector's onTapDown parameter should be of type "Function(TapDownDetails details)". Currently you're passing VoidCallback in to it.
I've left only the parts that need to be corrected.
class ReusableAgeWeightCard extends StatelessWidget {
final GestureTapDownCallback onTapDownMinus;
final GestureTapDownCallback onTapDownPlus;
}
And when you're using your new widget - don't forget to pass the right function in to those params.
In your example above, the "onTapDownPlus" definition is incorrect.
ReusableAgeWeightCard(
onTapDownMinus: (details) {}, // This one is correct in your code
onTapDownPlus: (details) {}, // This one has to be fixed
)
If you're not going to use "details" in the function code, you can always define the function as in example below (using "empty" parameters).
ReusableAgeWeightCard(
onTapDownMinus: (_) {},
onTapDownPlus: (_) {},
)
UPD: Added the full widget code with the "stack widget at index 0" fix.
class ReusableAgeWeightCard extends StatelessWidget {
final Widget changeMode;
final String label;
final String unit;
final int si;
final GestureTapDownCallback onTapDownMinus;
final Function onTapUp;
final Function onTapCancel;
final Function onPressMinus;
final GestureTapDownCallback onTapDownPlus;
final Function onPressPlus;
ReusableAgeWeightCard({
#required this.label,
this.changeMode,
this.unit,
#required this.si,
#required this.onTapDownMinus,
#required this.onTapUp,
#required this.onTapCancel,
#required this.onPressMinus,
#required this.onTapDownPlus,
#required this.onPressPlus,
});
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(6.0),
margin: EdgeInsets.all(15.0),
decoration: BoxDecoration(
color: kActiveCardColor,
borderRadius: BorderRadius.circular(15.0),
),
child: Stack(
alignment: Alignment.topRight,
children: <Widget>[
if( changeMode != null) changeMode, // <-- Fixed this line with a conditional rendering
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(
label,
style: kLabelTextStyle,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: <Widget>[
Text(
si.toString(),
style: kNumberMediumTextStyle,
),
Text(
unit,
style: kLabelTextStyle,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTapDown: onTapDownMinus,
onTapUp: onTapUp,
onTapCancel: onTapCancel,
onTap: onPressMinus,
child: RawMaterialButton(
elevation: 6.0,
fillColor: Color(0xff4c4f5e),
shape: CircleBorder(),
constraints: BoxConstraints.tightFor(
height: 56.0,
width: 56.0,
),
child: Icon(
FontAwesomeIcons.minus,
size: 25.0,
color: Colors.white,
),
),
),
SizedBox(
width: 10.0,
),
GestureDetector(
onTapDown: onTapDownPlus,
onTapUp: onTapUp,
onTapCancel: onTapCancel,
onTap: onPressPlus,
child: RawMaterialButton(
elevation: 6.0,
fillColor: Color(0xff4c4f5e),
shape: CircleBorder(),
constraints: BoxConstraints.tightFor(
height: 56.0,
width: 56.0,
),
child: Icon(
FontAwesomeIcons.plus,
size: 25.0,
color: Colors.white,
),
),
),
],
)
],
),
],
),
);
}
}