Related
Working on a flutter project and the code is stable on android every thing just working fine but when I want to debug at ios I am getting below errors. Could not understand why it is happing.
Any idea would help.
The following StackOverflowError was thrown building UnmanagedRestorationScope:
Stack Overflow
The relevant error-causing widget was
TextFormField
lib/…/login/loginPage.dart:63
When the exception was thrown, this was the stack
════════ Exception caught by widgets library ═══════════════════════════════════
'package:flutter/src/widgets/framework.dart': Failed assertion: line 4531 pos 14: 'owner!._debugCurrentBuildTarget == this': is not true.
package:flutter/…/widgets/framework.dart:4531
The relevant error-causing widget was
TextFormField
and the error point it out to loginPage widget is
Padding(
padding: const EdgeInsets.only(top: 40, left: 40, right: 40),
child: TextFormField(
controller: viewModel.usernameText,
decoration: InputDecoration(
prefixIcon: const Icon(
Icons.account_circle,
color: qPrimaryColor,
),
hintText: PageTextConst.username,
labelText: PageTextConst.username,
labelStyle: const TextStyle(fontSize: 18)),
validator: (String? text) {
if (text!.isEmpty) {
return PageTextConst.enterUsername;
} else if (text.length < 6) {
return PageTextConst.falseUsername;
} else {
return "";
}
},
),
),
EDIT :
TextFormField controller
class LoginAuthViewModel extends BaseViewModel {
String versionName = "";
TextEditingController usernameText = TextEditingController();
TextEditingController passwordText = TextEditingController();
Padding(
padding: const EdgeInsets.only(top: 40, left: 40, right: 40),
child: SizedBox(
height:50,
width:100,
child: TextFormField(
controller: viewModel.usernameText,
decoration: InputDecoration(
prefixIcon: const Icon(
Icons.account_circle,
color: qPrimaryColor,
),
hintText: PageTextConst.username,
labelText: PageTextConst.username,
labelStyle: const TextStyle(fontSize: 18)),
validator: (String? text) {
if (text!.isEmpty) {
return PageTextConst.enterUsername;
} else if (text.length < 6) {
return PageTextConst.falseUsername;
} else {
return "";
}
},
),
),)
Simply add the sized box around the textformfield
I am trying to get an auth form to conditionally redirect in a flutter StreamBuilder widget using a ternary statement.
When the redirect condition returns true I get a red screen and the following log:
I/flutter ( 3787): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 3787): The following assertion was thrown building StreamBuilder<Map<dynamic, dynamic>>(dirty, state:
I/flutter ( 3787): _StreamBuilderBaseState<Map<dynamic, dynamic>, AsyncSnapshot<Map<dynamic, dynamic>>>#66400):
I/flutter ( 3787): setState() or markNeedsBuild() called during build.
I/flutter ( 3787): This Overlay widget cannot be marked as needing to build because the framework is already in the
I/flutter ( 3787): process of building widgets. A widget can be marked as needing to be built during the build phase
I/flutter ( 3787): only if one of its ancestors is currently building. This exception is allowed because the framework
I/flutter ( 3787): builds parent widgets before children, which means a dirty descendant will always be built.
I/flutter ( 3787): Otherwise, the framework might not visit this widget during this build phase.
I/flutter ( 3787): The widget on which setState() or markNeedsBuild() was called was:
I/flutter ( 3787): Overlay-[LabeledGlobalKey<OverlayState>#4f97a](state: OverlayState#5df28(tickers: tracking 2
I/flutter ( 3787): tickers, entries: [OverlayEntry#09e48(opaque: false; maintainState: false),
I/flutter ( 3787): OverlayEntry#61a61(opaque: false; maintainState: true), OverlayEntry#79842(opaque: false;
I/flutter ( 3787): maintainState: false), OverlayEntry#11ff2(opaque: false; maintainState: true)]))
I/flutter ( 3787): The widget which was currently being built when the offending call was made was:
I/flutter ( 3787): StreamBuilder<Map<dynamic, dynamic>>(dirty, state: _StreamBuilderBaseState<Map<dynamic, dynamic>,
I/flutter ( 3787): AsyncSnapshot<Map<dynamic, dynamic>>>#66400)
Offending widget:
import 'package:flutter/material.dart';
import '../blocs/auth_bloc.dart';
class LoginPage extends StatelessWidget {
final authBloc = AuthBloc();
Map<String, bool> initialData = {'loginSuccess': false, 'isLoading': false};
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: authBloc.redirect,
initialData: initialData,
builder: (context, snapshot) {
return Scaffold(body: _render(context, snapshot));
});
}
Widget _render(BuildContext context, AsyncSnapshot snapshot) {
return !snapshot.data['loginSuccess'] && snapshot.data['isLoading']
? _circularSpinner()
: snapshot.data['loginSuccess'] && !snapshot.data['isLoading']
? _redirect(context)
: _buildPage();
}
_redirect(BuildContext context) {
return Navigator.pushReplacementNamed(context, '/dashboard');
}
Widget _buildPage() {
return Container(
margin: EdgeInsets.all(20.0),
child: Center(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
_emailField(authBloc),
_padding(),
_passwordField(authBloc),
_padding(),
_submitButton(authBloc)
],
),
),
),
);
}
Widget _circularSpinner() {
return Center(
child: CircularProgressIndicator(),
);
}
Widget _emailField(AuthBloc authBloc) {
return StreamBuilder(
stream: authBloc.email,
builder: (BuildContext context, snapshot) {
return TextField(
onChanged: authBloc.emailChanged,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: 'you#example.com',
labelText: 'Email Address',
errorText: snapshot.error,
border: OutlineInputBorder(),
),
);
},
);
}
Widget _passwordField(AuthBloc authBloc) {
return StreamBuilder(
stream: authBloc.password,
builder: (BuildContext context, snapshot) {
return TextField(
onChanged: authBloc.passwordChanged,
obscureText: true,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: '8 characters or more with at least 1 number',
labelText: 'Password',
errorText: snapshot.error,
border: OutlineInputBorder(),
),
);
},
);
}
Widget _padding() {
return Padding(
padding: EdgeInsets.only(top: 20.0),
);
}
Widget _submitButton(AuthBloc authBloc) {
return StreamBuilder(
stream: authBloc.submitValid,
builder: (context, snapshot) {
return RaisedButton(
child: Text('Login'),
color: Colors.blue,
onPressed: snapshot.hasError ? null : authBloc.submitForm,
);
});
}
}
I have googled but cannot find anything relating to Navigator in this context.
I expect the Widget to redirect to the 'dashboard' widget. Instead I get red error screen.
I run today into the same problem. I tried the solution from #user8467470 but StreamBuilder is already registered to my Stream. So I ended up with this solution:
#override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<Response<ExchangeRate>>(
stream: _bloc.exchangeDataStream,
builder: (context, snapshot) {
if (snapshot.hasData) {
switch (snapshot.data.status) {
case Status.LOADING:
return LoadingWidget(loadingMessage: snapshot.data.message);
case Status.COMPLETED:
WidgetsBinding.instance.addPostFrameCallback((_) {
Navigator.pushReplacementNamed(context, '/home');
});
break;
case Status.ERROR:
return Container(
child: Text(snapshot.data.message),
);
}
}
return Container();
}));
}
This way I have only one stream in my bloc.
I have found a work around but it isn't pretty. I thought I would share it here in case anyone else was having the same problem but I of course expect other more experienced Flutter devs to offer a better solution and rationale.
It seems that for whatever reason StreamBuilder does not like you Navigating away in the builder function due to its build flow. As a result I moved the navigate away outside of the StreamBuilder but inside the build method and added a listener like this:
#override
Widget build(BuildContext context) {
// Manually listening for redirect conidtions here
// once a response is received from the server
authBloc.loginSuccess.listen((data) {
if (data) {
Navigator.pushReplacementNamed(context, '/dashboard');
}
});
return StreamBuilder(
stream: authBloc.isLoading,
initialData: false,
builder: (context, snapshot) {
print(snapshot.data);
return Scaffold(
body: snapshot.data ? _circularSpinner() : _buildPage(),
);
});
}
It seems to work now but will keep my eye on best practice for this.
I am trying to user Streambuilder to display gridview, but it return this error, I am calling the method classList() to container in scaffold body
database = FirebaseDatabase.instance
I want to show classData, show 0,1,2..etc I want to show ('className','classSection' in one button per child) in gridview as RaisedButtons
I get this error when the code below is executed
I/flutter ( 5433): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 5433): The following NoSuchMethodError was thrown building HomePage(dirty, state: _HomePage#055be):
I/flutter ( 5433): The method 'split' was called on null.
I/flutter ( 5433): Receiver: null
I/flutter ( 5433): Tried calling: split("/")
I/flutter ( 5433):
I/flutter ( 5433): When the exception was thrown, this was the stack:
I/flutter ( 5433): #0 Object.noSuchMethod (dart:core/runtime/libobject_patch.dart:50:5)
I/flutter ( 5433): #1 DatabaseReference.child (file:///G:/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_database-2.0.3/lib/src/database_reference.dart:24:58)
I/flutter ( 5433): #2 _HomePage.classList (package:barcode_scan_example/home_page.dart:169:44)
I/flutter ( 5433): #3 _HomePage.build (package:barcode_scan_example/home_page.dart:265:30)
I/flutter ( 5433): #4 StatefulElement.build (package:flutter/src/widgets/framework.dart:3825:27)
I/flutter ( 5433): #5 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3736:15)
I/flutter ( 5433): #6 Element.rebuild (package:flutter/src/widgets/framework.dart:3559:5)
I/flutter ( 5433): #7 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:3716:5)
I/flutter ( 5433): #8 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:3864:11)
I/flutter ( 5433): #9 ComponentElement.mount (package:flutter/src/widgets/framework.dart:3711:5)
I/flutter ( 5433): #10 Element.inflateWidget (package:flutter/src/widgets/framework.dart:2956:14)
I/flutter ( 5433): #11 Element.updateChild (package:flutter/src/widgets/framework.dart:2759:12)
I/flutter ( 5433): #12 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3747:16)
I/flutter ( 5433): #13 Element.rebuild (package:flutter/src/widgets/framework.dart:3559:5)
I/flutter ( 5433): #14 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2273:33)
I/flutter ( 5433): #15 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:700:20)
I/flutter ( 5433): #16 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:268:5)
I/flutter ( 5433): #17 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:988:15)
I/flutter ( 5433): #18 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:928:9)
I/flutter ( 5433): #19 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:840:5)
I/flutter ( 5433): #23 _invoke (dart:ui/hooks.dart:209:10)
I/flutter ( 5433): #24 _drawFrame (dart:ui/hooks.dart:168:3)
I/flutter ( 5433): (elided 3 frames from package dart:async)
classList() {
StreamBuilder(
stream:
database.reference().child('user').child(userUid).child('classData').orderByKey().onValue,
builder: (BuildContext context, AsyncSnapshot<Event> snapshot) {
if (snapshot.hasData) {
if (snapshot.data.snapshot.value != null) {
Map<dynamic, dynamic> map = snapshot.data.snapshot.value;
List<dynamic> list = map.values.toList();
print("list is : $list");
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3),
itemCount: list.length,
padding: EdgeInsets.all(2.0),
itemBuilder: (BuildContext context, int index) {
print("print job ${list[index]["className"]}");
return Container(
child: RaisedButton(
onPressed: null,
child: Text(
"${list[index]["className"]}\n ${list[index]["classSection"]}"),
),
padding: EdgeInsets.all(2.0),
);
},
);
} else {
return Container(
child: Center(
child: Text(
"There's no Class registered in the system",
style: TextStyle(fontSize: 20.0, color: Colors.grey),
textAlign: TextAlign.center,
)));
}
} else {
return CircularProgressIndicator();
}
});
}
the entire dart file
import 'package:flutter/material.dart';
import 'auth.dart';
import 'auth_provider.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/services.dart';
import 'make_class.dart';
import 'dart:async';
import 'package:barcode_scan/barcode_scan.dart';
import 'package:firebase_database/firebase_database.dart';
import 'qr_screen.dart';
class HomePage extends StatefulWidget {
#override
_HomePage createState() => _HomePage();
}
enum ScaffoldType { student, lecturer }
ScaffoldType _scaffoldType = ScaffoldType.lecturer;
class _HomePage extends State<HomePage> {
final FirebaseDatabase database = FirebaseDatabase.instance;
String barcode = "";
String userUid;
var userClass;
Future<void> _signOut(BuildContext context) async {
try {
final BaseAuth auth = AuthProvider.of(context).auth;
await auth.signOut();
} catch (e) {
print(e);
}
}
#override
void initState() {
super.initState();
userUi();
setState(() async* {
FirebaseDatabase database;
database = FirebaseDatabase.instance;
database.setPersistenceEnabled(true);
database.setPersistenceCacheSizeBytes(10000000);
});
}
Future reUser() async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
print(user.uid);
var userUid = user.uid;
var userWho = await database
.reference()
.child('user')
.child(userUid)
.once()
.then((DataSnapshot snapshot) {
Map<dynamic, dynamic> data = snapshot.value;
var isL = data.values.toList();
print(isL[1]);
print(data.values);
if (isL[1].toString().toLowerCase() == "true") {
_scaffoldType = ScaffoldType.lecturer;
print('lecturer');
} else if (isL[1].toString().toLowerCase() == "false") {
_scaffoldType = ScaffoldType.student;
print("student");
}
});
// print(userWho);
}
userUi() async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
print(user.uid);
return user.uid;
}
classList(userUid) {
print(userUid);
StreamBuilder(
stream:
database.reference().child('user').child(userUid).child('classData').orderByKey().onValue,
builder: (BuildContext context, AsyncSnapshot<Event> snapshot) {
if (snapshot.hasData) {
if (snapshot.data.snapshot.value != null) {
Map<dynamic, dynamic> map = snapshot.data.snapshot.value;
List<dynamic> list = map.values.toList();
print("list is : $list");
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3),
itemCount: list.length,
padding: EdgeInsets.all(2.0),
itemBuilder: (BuildContext context, int index) {
print("print job ${list[index]["className"]}");
return Container(
child: RaisedButton(
onPressed: (){},
child: Text(
"${list[index]["className"]}\n ${list[index]["classSection"]}"),
),
padding: EdgeInsets.all(2.0),
);
},
);
} else {
return Container(
child: Center(
child: Text(
"There's no Class registered in the system",
style: TextStyle(fontSize: 20.0, color: Colors.grey),
textAlign: TextAlign.center,
)));
}
} else {
return CircularProgressIndicator();
}
});
}
#override
Widget build(BuildContext context) {
// var userUid = userUi();
reUser();
return Scaffold(
appBar: AppBar(
title: Text('Welcome'),
actions: <Widget>[
FlatButton(
child: Icon(Icons.exit_to_app),
onPressed: () => _signOut(context),
)
],
),
bottomNavigationBar: BottomAppBar(
notchMargin: 8.0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Padding(
padding: const EdgeInsets.fromLTRB(35, 0, 35, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: buttonBelow(),
),
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: buttonBelow2(),
),
],
),
),
),
shape: CircularNotchedRectangle(),
),
resizeToAvoidBottomInset: true,
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: Container(
height: 80,
width: 80,
child: FittedBox(
child: FloatingActionButton(
onPressed: scan,
child: Icon(
Icons.camera,
size: 35,
),
elevation: 2.0,
),
),
),
body: Container(child: classList(userUi()),),
);
}
List<Widget> buttonBelow() {
if (_scaffoldType == ScaffoldType.lecturer) {
return <Widget>[
FlatButton(
child: Icon(
Icons.add_circle,
semanticLabel: "Add Class",
size: 45,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MakeClass()),
);
},
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(180)),
),
Text("Add Class")
];
} else {
return <Widget>[
Opacity(
opacity: 0,
child: FlatButton(
onPressed: () {},
child: Icon(
Icons.add_circle,
semanticLabel: "Add Class",
size: 45,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(180)),
),
),
Opacity(opacity: 0, child: Text("Add Class"))
];
}
}
List<Widget> buttonBelow2() {
if (_scaffoldType == ScaffoldType.lecturer) {
return <Widget>[
FlatButton(
child: Icon(
Icons.blur_on,
semanticLabel: "QRCode",
size: 45,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => QrScreen()),
);
},
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(180)),
),
Text("QRCode")
];
}
}
Future scan() async {
try {
String barcode = await BarcodeScanner.scan();
setState(() => this.barcode = barcode);
} on PlatformException catch (e) {
if (e.code == BarcodeScanner.CameraAccessDenied) {
setState(() {
this.barcode = 'The user did not grant the camera permission!';
});
} else {
setState(() => this.barcode = 'Unknown error: $e');
}
} on FormatException {
setState(() => this.barcode =
'null (User returned using the "back"-button before scanning anything. Result)');
} catch (e) {
setState(() => this.barcode = 'Unknown error: $e');
}
}
}
Main problem is when we pass blank or null string in ".child()" method of firebase, it will give us split("/") error because internally it will try to split from string and get try to get data
from it.
Now the problem in your code is you are calling "classList(userUid)" in the widget override method before the data come from firebase userid with use of StreamBuilder() but the userUid is blank and as i said above,
firebase will give us split("/") error if we pass blank or null in that ".child()" method.
So the conclusion is we have to wait for firebase userid until we get it from async result because to get firebase userid which is async task and we have to wait for that until result come with using await keyword.
So Here is the answer, how to do that:
You have to replace your body portion in widget with the use of future<> such as below:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Welcome'),
actions: <Widget>[
FlatButton(
child: Icon(Icons.exit_to_app),
onPressed: () => _signOut(context),
)
],
),
bottomNavigationBar: BottomAppBar(
notchMargin: 8.0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Padding(
padding: const EdgeInsets.fromLTRB(35, 0, 35, 0),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: buttonBelow(),
),
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: buttonBelow2(),
),
],
),
),
),
shape: CircularNotchedRectangle(),
),
resizeToAvoidBottomInset: true,
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: Container(
height: 80,
width: 80,
child: FittedBox(
child: FloatingActionButton(
onPressed: scan,
child: Icon(
Icons.camera,
size: 35,
),
elevation: 2.0,
),
),
),
body: new FutureBuilder<FirebaseUser>(
future: FirebaseAuth.instance.currentUser(),
builder: (BuildContext context, AsyncSnapshot<FirebaseUser> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return new Container(child: classList(snapshot.data.uid));
}
else {
return new Text('Loading...');
}
},
),
);
}
Also the best practice is that you have to get firebase userid only in "initState()" method which will call only once during lifecycle. so declare "FirebaseUser user" globally in your class and then call your "userUi()"
in only "initState()" method.
The method 'split' was called on null.
This type of exceptions occurs whenever you are referencing a path that doesn't exist. So make sure the path of your firebase database is correct.
This is the variable initialisation
var displayResult = '';
Here is the on press code
Padding(
padding: EdgeInsets.all(5.0),
child: Row(
children: <Widget>[
Expanded(
child: RaisedButton(
color: Theme
.of(context)
.primaryColor,
textColor: Theme
.of(context)
.primaryColorLight,
child: Text("calculate"),
onPressed: () {
setState(() {
this.displayResult = _calculateTotalReturn();
});
},
)),
This the function Im trying to call
String _calculateTotalReturn() {
setState(() {
double principle = double.parse(principleController.text);
double roi = double.parse(roiController.text);
double term = double.parse(termController.text);
double tap = principle + (principle * roi * term) / 100;
String result = "After $term years, your investment will worth $tap $_currentItemSelected";
return result;
});
}
This is the error I'm getting
Performing hot reload...
Syncing files to device iPhone XR...
flutter: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
flutter: The following assertion was thrown building SIForm(dirty, dependencies:
flutter: [_LocalizationsScope-[GlobalKey#4c1f9], _InheritedTheme], state: _SIFormState#b2966):
flutter: 'package:flutter/src/widgets/text.dart': Failed assertion: line 237 pos 15: 'data != null': is not
flutter: true.
flutter:
flutter: Either the assertion indicates an error in the framework itself, or we should provide substantially
flutter: more information in this error message to help you determine and fix the underlying cause.
flutter: In either case, please report this assertion by filing a bug on GitHub:
flutter: https://github.com/flutter/flutter/issues/new?template=BUG.md
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #2 new Text (package:flutter/src/widgets/text.dart:237:15)
flutter: #3 _SIFormState.build (package:simple_cal/main.dart:153:24)
flutter: #4 StatefulElement.build (package:flutter/src/widgets/framework.dart:3825:27)
flutter: #5 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3736:15)
flutter: #6 Element.rebuild (package:flutter/src/widgets/framework.dart:3559:5)
flutter: #7 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2273:33)
flutter: #8 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:700:20)
flutter: #9 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:268:5)
flutter: #10 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:988:15)
flutter: #11 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:928:9)
flutter: #12 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:749:7)
flutter: #14 _Timer._runTimers (dart:isolate/runtime/libtimer_impl.dart:382:19)
flutter: #15 _Timer._handleMessage (dart:isolate/runtime/libtimer_impl.dart:416:5)
flutter: #16 _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
flutter: (elided 3 frames from class _AssertionError and package dart:async)
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════
Reloaded 1 of 432 libraries in 641ms.
This is the complete main.dart file
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
Widget MyApp() {
return MaterialApp(
title: 'Simple Intrest app',
home: SIForm (),
theme: ThemeData(
primaryColor: Colors.deepPurple,
accentColor: Colors.deepPurpleAccent
),
);
}
class SIForm extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _SIFormState ();
}
}
class _SIFormState extends State<SIForm> {
var _currencies = ["INR", "USD", "CAD"];
var _currentItemSelected = "INR";
var displayResult = '';
TextEditingController principleController = TextEditingController();
TextEditingController roiController = TextEditingController();
TextEditingController termController = TextEditingController();
#override
Widget build(BuildContext context) {
TextStyle textStyle = Theme
.of(context)
.textTheme
.title;
return Scaffold(
appBar: AppBar(
title: Text("Simple Interest Calc"),
),
body: Container(padding: EdgeInsets.only(top: 50.0),
child: ListView(
children: <Widget>[
Padding(
padding: EdgeInsets.all(5.0),
child: TextField(
keyboardType: TextInputType.number,
controller: principleController,
decoration: InputDecoration(
labelText: 'principle',
hintText: '0.00',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0)
)
),
)),
Padding(
padding: EdgeInsets.all(5.0),
child: TextField(
controller: roiController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'Rate of Interest',
hintText: '0.00',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0)
)
),
)),
Padding(
padding: EdgeInsets.all(5.0),
child: Row(
children: <Widget>[
Expanded(child: TextField(
controller: termController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'Terms',
hintText: '%',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5.0)
)
),
)),
Container(width: 10.0),
Expanded(
child: DropdownButton<String>(
items: _currencies.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
value: _currentItemSelected,
onChanged: (val) {
_ondropDownChange(val);
},),
),
],
)),
Padding(
padding: EdgeInsets.all(5.0),
child: Row(
children: <Widget>[
Expanded(
child: RaisedButton(
color: Theme
.of(context)
.primaryColor,
textColor: Theme
.of(context)
.primaryColorLight,
child: Text("calculate"),
onPressed: () {
setState(() {
this.displayResult = _calculateTotalReturn();
});
},
)),
Container(width: 5.0),
Expanded(
child: RaisedButton(
color: Theme
.of(context)
.accentColor,
textColor: Theme
.of(context)
.primaryColorLight,
child: Text("Reset"),
onPressed: () {
setState(() {
// _reset();
});
}
)),
],
)),
Padding(
padding: EdgeInsets.all(5.0),
child: Text(this.displayResult),
)
],
),
),
);
}
void _ondropDownChange(String value) {
setState(() {
this._currentItemSelected = value;
});
}
String _calculateTotalReturn() {
setState(() {
double principle = double.parse(principleController.text);
double roi = double.parse(roiController.text);
double term = double.parse(termController.text);
double tap = principle + (principle * roi * term) / 100;
String result = "After $term years, your investment will worth $tap $_currentItemSelected";
return result;
});
}
void _reset() {
setState(() {
this.principleController.text = " ";
this.roiController.text = " ";
this.termController.text = " ";
this.displayResult = " ";
});
}
}
You should get rid of the setState in _calculateTotalReturn. The return result; there is returning from the inline function that you give to setState and _calculateTotalReturn actually returns null.
I trying to add a Drop down inside a Row.
When I do this
Row(
children: <Widget>[
Expanded(child:TextField(
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'Terms',
hintText: '%'
),
)),
Expanded(child:DropdownButton<String>(
items:_currencies.map((String value){
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
value : 'Rupee',
)),
],
)
Im getting a error
erforming hot reload...
Syncing files to device iPhone XR...
flutter: ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
flutter: The following assertion was thrown building SIForm(dirty, state: _SIFormState#da46e):
flutter: 'package:flutter/src/material/dropdown.dart': Failed assertion: line 560 pos 15: 'items == null ||
flutter: items.isEmpty || value == null || items.where((DropdownMenuItem<T> item) => item.value ==
flutter: value).length == 1': is not true.
flutter:
flutter: Either the assertion indicates an error in the framework itself, or we should provide substantially
flutter: more information in this error message to help you determine and fix the underlying cause.
flutter: In either case, please report this assertion by filing a bug on GitHub:
flutter: https://github.com/flutter/flutter/issues/new?template=BUG.md
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #2 new DropdownButton (package:flutter/src/material/dropdown.dart:560:15)
flutter: #3 _SIFormState.build (package:simple_cal/main.dart:65:31)
flutter: #4 StatefulElement.build (package:flutter/src/widgets/framework.dart:3825:27)
flutter: #5 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3736:15)
flutter: #6 Element.rebuild (package:flutter/src/widgets/framework.dart:3559:5)
flutter: #7 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2273:33)
flutter: #8 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:700:20)
flutter: #9 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:268:5)
flutter: #10 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:988:15)
flutter: #11 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:928:9)
flutter: #12 _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:749:7)
flutter: #14 _Timer._runTimers (dart:isolate/runtime/libtimer_impl.dart:382:19)
flutter: #15 _Timer._handleMessage (dart:isolate/runtime/libtimer_impl.dart:416:5)
flutter: #16 _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:171:12)
flutter: (elided 3 frames from class _AssertionError and package dart:async)
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════
Reloaded 1 of 432 libraries in 736ms.
Here is my full main.dart file
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
Widget MyApp() {
return MaterialApp(
title: 'Simple Intrest app',
home: SIForm (),
);
}
class SIForm extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _SIFormState ();
}
}
class _SIFormState extends State<SIForm>{
var _currencies = ["Rupees","USD","CAD"];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title:Text("Simple Interest Calc"),
),
body: Container(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top : 5.0,bottom : 5.0),
child: TextField(
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'principle',
hintText: 'Enter the principle amout'
),
)),
Padding(
padding: EdgeInsets.only(top : 5.00*2,bottom : 5.00*2),
child : TextField(
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'Rate of Interest',
hintText: '%'
),
)),
Row(
children: <Widget>[
Expanded(child:TextField(
keyboardType: TextInputType.number,
decoration: InputDecoration(
labelText: 'Terms',
hintText: '%'
),
)),
Expanded(child:DropdownButton<String>(
items:_currencies.map((String value){
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
value : 'Rupee',
)),
],
)
],
),
),
);
}
}
documentation of DropdownButton says
value: 'Rupees'
not
value: 'Rupee'
because
var _currencies = ["Rupees","USD","CAD"];
and you have to add
onChanged: (str){},
Change from value to "Rupees" and add onChanged function
DropdownButton<String>(
items:_currencies.map((String value){
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
value : 'Rupees',
onChanged: (val){},),