form.currentstate.validate() failing - Flutter - google-maps

I need some help with this. My task is to pick the location along with the address and submit it. But for some reasons, the _addPointKey.currentState.validate() is always giving false.
I have a TextFormField for taking the address, a location preview container, a button to open the google_map_location_picker and finally a button to submit the data. All these fields are declared inside a form with _addPointKey key.
Form validation does work, i.e. if the fields are empty, it does show in red that the fields can't be empty. But still, I have some problem with submitting the whole formData. The textFormField becomes null.
I have used google_map_location_picker package for picking the location. Can somebody help?
Thanks in advance.
final GlobalKey<FormState> _addPointKey = GlobalKey<FormState>();
Map<String, dynamic> formData = {
"address": null,
};
Widget _addressField() {
return Container(
margin: EdgeInsets.symmetric(vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Address of the Collection Center",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: Theme.of(context).primaryColor),
),
SizedBox(
height: 10,
),
TextFormField(
decoration: InputDecoration(
border: InputBorder.none,
fillColor: Color(0xfff3f3f4),
filled: true),
maxLines: 4,
validator: (String value) {
if (value.isEmpty) {
return "Address is required";
}
return '';
},
onChanged: (String value) {
formData["address"] = value;
},
onSaved: (String value) {
formData["address"] = value;
},
),
],
),
);
}
Widget _locationPreview() {
return (_pickedLocation != null)
? Container(
height: 300,
decoration: BoxDecoration(
border: Border.all(
width: 2,
color: Theme.of(context).accentColor,
)),
child: GoogleMap(
initialCameraPosition: CameraPosition(
target: _pickedLocation.latLng,
zoom: 14.4746,
),
markers: Set.from(newMarkers),
),
)
: Container(
child: Text(
"Location is required.",
style: TextStyle(
color: Colors.red,
),
),
);
}
Widget _locationButton() {
return RaisedButton(
color: Theme.of(context).accentColor,
onPressed: () async {
LocationResult result = await showLocationPicker(
context,
< API key>,
initialCenter: LatLng(31.1975844, 29.9598339),
myLocationButtonEnabled: true,
layersButtonEnabled: true,
);
setState(() {
_pickedLocation = result;
_addPointKey.currentState.save();
newMarkers.add(Marker(
markerId: MarkerId("newId"),
draggable: false,
position: _pickedLocation.latLng,
onTap: null,
));
});
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.location_on,
color: Colors.white,
),
Text(
(_pickedLocation == null) ? 'Locate on Map' : 'Change Location',
style: TextStyle(color: Colors.white),
),
],
),
);
}
Widget _addLocationButton() {
return ScopedModelDescendant<MainModel>(
builder: (BuildContext context, Widget widget, MainModel model) {
return model.managingCenter
? CircularProgressIndicator()
: InkWell(
onTap: () async {
print(_addPointKey.currentState.validate());
if (!_addPointKey.currentState.validate() ||
_pickedLocation == null) {
print(formData);
return;
}
_addPointKey.currentState.save();
Map<String, dynamic> successInfo =
await model.addCenter(model.token, formData);
if (successInfo["success"]) {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FutureBuilder(
future: model.fetchCenter(model.token),
builder: (context, authResultSnapShot) {
return authResultSnapShot.connectionState ==
ConnectionState.waiting
? SplashScreen()
: CollectionPoints(model);
})));
} else {
print("Something went wrong");
}
},
child: Container(
height: 50,
alignment: Alignment.center,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
boxShadow: <BoxShadow>[
BoxShadow(
color: Colors.grey.shade200,
offset: Offset(2, 4),
blurRadius: 5,
spreadRadius: 2)
],
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [Color(0xfffbb448), Color(0xfff7892b)]),
),
padding: const EdgeInsets.all(10.0),
child: Text('Add the Location',
style: TextStyle(fontSize: 20, color: Colors.white)),
),
);
});
}
void _addPoint() {
showBottomSheet(
context: context,
builder: (context) {
return Container(
padding: EdgeInsets.all(10),
child: Form(
key: _addPointKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
_addressField(),
_locationPreview(),
_locationButton(),
_addLocationButton()
],
),
),
),
);
});
}

In the TextFormField validator function you must return null, it indicates the field has correct value and there are no errors. Returning anything other than null will indicate that the field has an invalid value, i've shared the corrected code of the validator function.
TextFormField(
decoration: InputDecoration(
border: InputBorder.none,
fillColor: Color(0xfff3f3f4),
filled: true),
maxLines: 4,
validator: (String value) {
if (value.isEmpty) {
return "Address is required";
}
// return ''; this is causing you the error you must return null
return null; // this is correct
},
onChanged: (String value) {
formData["address"] = value;
},
onSaved: (String value) {
formData["address"] = value;
},
),

A simpler way to create a confirm password on your flutter.
'showSnackBar' bottom pop-up to alert users for errors.
[1]: https://i.stack.imgur.com/zjXLd.png
var _password = '';
var _confirmPassword = '';
// this will called 'onTap'
void signUpUser() async {
if (_password != _confirmPassword){ // you can add your statements here
showSnackBar(context,
"Password does not match. Please re-type again.");
} else {
FirebaseAuthMethods(FirebaseAuth.instance).signUpWithEmail(
email: emailController.text,
password: passwordController.text,
context: context,
);
}
}
// Insert inside your build()
// to you password field.
child: TextFormField(
controller: passwordController,
obscureText: true,
onChanged: (value) {
_password = value;
},
// to your confirm password field.
child: TextFormField(
controller: confirmPasswordController,
obscureText: true,
onChanged: (value) {
_confirmPassword = value;
},
// add this to your Sign-up button
onTap: signUpUser,

Related

Variable that holds JSON data changes to null after I switch to other widgets group

I am havin this issue where I have a two step form. There is a local JSON file that I load initiating the state to use on the second step in a dropdown widget. However, when I click the continue button and switch to the second form, the variable changes to null causing to get the error "The method 'map' was called on null". I have tried loading the data in the onPressed function of the continueButton Widget, and tried to load again when creating one of the widget of the second form. But I always get this error that the map function was called on null. Help please !!!
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_signin_button/flutter_signin_button.dart';
import 'package:ofepaw/services/auth.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;
class RegisterPage extends StatefulWidget {
final Function toggleView;
RegisterPage({this.toggleView});
#override
State createState() => RegisterPageState();
}
class RegisterPageState extends State<RegisterPage> {
final AuthService _auth = AuthService();
// store the step we are in
int step = 1;
// Text Field
String emailOrPhone = "";
String pass = "";
String verifyPass = "";
String firstName = "";
String lastName = "";
String department = "";
String arrondissement = "";
String commune = "";
// variable for errors
String error = "";
// array containing the forms
var form1;
var form2;
// Controllers for the Textfields
final _emailOrPhoneController = TextEditingController();
final _passwordController = TextEditingController();
final _verifyPassController = TextEditingController();
final _firstNameController = TextEditingController();
final _lastNameController = TextEditingController();
//final _departmentController = TextEditingController();
//load the geographic division of Haiti json file
var division;
// get the locations data
Future<void> loadDivision() async {
String jsonString = await rootBundle
.loadString('assets/haiti_administrative_district.json');
Map<String, dynamic> map = json.decode(jsonString);
List<dynamic> data = map["departments"];
setState(() {
division = data;
});
}
// function to register user in ofepaw database
Future registerUser(
String id, String fname, String lname, String department) async {
final String url = "url go here";
final response = await http.post(url, body: {
"id": id,
"fname": fname,
"lname": lname,
"department": department
});
if (response.statusCode == 201) {
print("This is the response from the server");
print(response.body);
print("Response passed");
} else {
print("Error occured");
}
print(" The response is : ");
print(response.body.toString());
}
//functions for switching forms
getForm(int form) {
if (form == 1) {
return form1;
} else if (form == 2) {
return form2;
}
}
#override
void initState() {
super.initState();
loadDivision();
print(division);
form1 = <Widget>[
firstForm(),
Text("Or Sign Up with social media"),
SizedBox(
height: 20,
),
socialMediaButtons(),
SizedBox(
height: 50,
),
InkWell(
onTap: () {
widget.toggleView();
},
child: Text("Have an account? Login"))
];
form2 = <Widget>[
secondForm(),
InkWell(
//back button
onTap: () => setState(() => step = 1),
child: Text("Back"))
];
}
// dispose all controllers
// dispose of all TextEditingControllers
#override
void dispose() {
_emailOrPhoneController.dispose();
_passwordController.dispose();
_verifyPassController.dispose();
_firstNameController.dispose();
_lastNameController.dispose();
//_departmentController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Material(
child: Expanded(
child: Stack(
children: <Widget>[
// banner with picture
Positioned(
child: banner(),
),
// Login Elements Container
Positioned(
child: Container(
margin: EdgeInsets.only(top: 300.0),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
spreadRadius: 5,
blurRadius: 20,
offset: Offset(0, 0))
],
borderRadius: BorderRadius.only(
topRight: Radius.circular(50),
topLeft: Radius.circular(50))),
child: Center(
child: Column(
children: getForm(step),
),
),
),
)
],
),
),
);
}
Widget banner() {
return Container(
height: 350,
decoration: BoxDecoration(color: Colors.white),
child: Center(
child: Image.network(
"https://image.freepik.com/free-vector/man-using-his-phone-instead-working_23-2148501890.jpg"),
),
);
}
Widget emailField() {
return TextFormField(
controller: _emailOrPhoneController,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(top: 10, left: 20, right: 20),
border: InputBorder.none,
hintText: "Email or Phone Number",
hintStyle: TextStyle(color: Colors.grey[400], fontSize: 15)),
onChanged: (val) {
setState(() => emailOrPhone = val);
},
);
}
Widget firstNameField() {
return TextFormField(
controller: _firstNameController,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(top: 10, left: 20, right: 20),
border: InputBorder.none,
hintText: "First Name",
hintStyle: TextStyle(color: Colors.grey[400], fontSize: 15)),
onChanged: (val) {
setState(() => firstName = val);
},
);
}
Widget lastNameField() {
return TextFormField(
controller: _lastNameController,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(top: 10, left: 20, right: 20),
border: InputBorder.none,
hintText: "Last Name",
hintStyle: TextStyle(color: Colors.grey[400], fontSize: 15)),
onChanged: (val) {
setState(() => lastName = val);
},
);
}
Widget departmentField() {
return DropdownButtonFormField(
items: division.map<DropdownMenuItem<String>>((value) {
return DropdownMenuItem<String>(
value: value["name"],
child: Text(value["name"]),
);
}).toList(),
hint: Text("Choose the department"),
onChanged: (value) {
setState(() {});
},
decoration: InputDecoration(
contentPadding: EdgeInsets.only(top: 10, left: 20, right: 20),
border: InputBorder.none,
hintStyle: TextStyle(color: Colors.grey[400], fontSize: 15)),
);
}
Widget arrondissementField() {
return DropdownButtonFormField(
items: [
DropdownMenuItem(
child: Text("Delmas"),
value: 1,
),
DropdownMenuItem(
child: Text("Petion-Ville"),
value: 2,
)
],
hint: Text("Choose the department"),
onChanged: (int value) {
setState(() {});
},
decoration: InputDecoration(
contentPadding: EdgeInsets.only(top: 10, left: 20, right: 20),
border: InputBorder.none,
hintStyle: TextStyle(color: Colors.grey[400], fontSize: 15)));
}
Widget communeField() {
return DropdownButtonFormField(
items: [
DropdownMenuItem(
child: Text("Delmas"),
value: 1,
),
DropdownMenuItem(
child: Text("Petion-Ville"),
value: 2,
)
],
hint: Text("Choose the department"),
onChanged: (int value) {
setState(() {});
},
decoration: InputDecoration(
contentPadding: EdgeInsets.only(top: 10, left: 20, right: 20),
border: InputBorder.none,
hintStyle: TextStyle(color: Colors.grey[400], fontSize: 15)));
}
Widget passwordField() {
return TextFormField(
controller: _passwordController,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(bottom: 5, left: 20, right: 20),
border: InputBorder.none,
hintText: "Password",
hintStyle: TextStyle(color: Colors.grey[400], fontSize: 15)),
onChanged: (val) {
setState(() => pass = val);
});
}
Widget verifyPasswordField() {
return TextFormField(
controller: _verifyPassController,
decoration: InputDecoration(
contentPadding: EdgeInsets.only(bottom: 5, left: 20, right: 20),
border: InputBorder.none,
hintText: "Reenter Password",
hintStyle: TextStyle(color: Colors.grey[400], fontSize: 15)),
onChanged: (val) {
setState(() => verifyPass = val);
});
}
Widget socialMediaButtons() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SignInButton(Buttons.Facebook,
mini: true, onPressed: () => print("Facebook Sign in ...")),
SignInButton(Buttons.Google,
//mini: true,
onPressed: () => print("Google Sign in ..."))
],
);
}
Widget continueButton() {
return ButtonTheme(
minWidth: 185.0,
height: 48.0,
child: RaisedButton(
color: Colors.black,
textColor: Colors.white,
child: Text("continue"),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(50.0)),
onPressed: () {
print(division);
setState(() {
step = 2;
});
},
));
}
Widget signUpButton() {
return ButtonTheme(
minWidth: 185.0,
height: 48.0,
child: RaisedButton(
color: Colors.black,
textColor: Colors.white,
child: Text("Sign Up"),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(50.0)),
onPressed: () async {
dynamic result =
await _auth.registerWithEmailAndPassword(emailOrPhone, pass);
if (result == null) {
setState(() => error = "Email or Password incorrect");
} else {
// Register user ID in the server database
registerUser(result.user.uid, firstName, lastName, department);
}
},
));
}
Widget emailPassField() {
return Container(
// Form input field
margin: EdgeInsets.only(top: 40.0),
width: 320.0,
height: 180.0,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
spreadRadius: 0.2,
blurRadius: 5,
offset: Offset(0, 0))
],
borderRadius: BorderRadius.circular(20)),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
emailField(),
Divider(),
passwordField(),
Divider(),
verifyPasswordField()
],
),
);
}
Widget personalInfoField() {
return Container(
// Form input field
margin: EdgeInsets.only(top: 40.0),
width: 320.0,
height: 310.0,
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
spreadRadius: 0.2,
blurRadius: 5,
offset: Offset(0, 0))
],
borderRadius: BorderRadius.circular(20)),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
firstNameField(),
Divider(),
lastNameField(),
Divider(),
departmentField(),
Divider(),
arrondissementField(),
Divider(),
communeField()
],
),
);
}
Widget firstForm() {
return Column(
children: <Widget>[
emailPassField(),
SizedBox(
height: 50,
),
continueButton(),
SizedBox(
height: 50,
),
],
);
}
Widget secondForm() {
return Column(
children: <Widget>[
personalInfoField(),
SizedBox(
height: 40,
),
signUpButton(),
SizedBox(
height: 40,
),
],
);
}
}
The root of your problem starts here String jsonString = await rootBundle.loadString('assets/haiti_administrative_district.json');
Are you sure your project can recognize thise: 'assets/haiti_administrative_district.json'? Have you added it to your assests in pubspec.yaml?
Because this is line is returning null, everything downward will b e returning null, including the error you are reciving.
Future<void> loadDivision() async {
String jsonString = await rootBundle
.loadString('assets/haiti_administrative_district.json');
Map<String, dynamic> map = json.decode(jsonString);
List<dynamic> data = map["departments"];
setState(() {
division = data;
});
}
Here, first make sure data is getting loaded in jsonString.
Second, make sure json.decode(jsonString) is returning json object and not array of json objects.
If it is returning array of json objects, store it in a List<Map>.
Then make a list like this:
List<Map> maps = json.decode(jsonString);
List data=new List();
maps.forEach((element)=>data.add(element['departments']));

ListView not displayed after update in Json Data

Status response code is 200 but the ListView is not displayed and stuck on the CircularProgressIndicator.
When I had 2 items in the Json data it was displaying just fine but as I added another item it doesn't show up!
I've tried removing ListView.separated and using ListView.builder instead and also tried using StreamBuilder but I don't seem to be using it correctly as I'm fairly new to Flutter. If I do have to use StreamBuilder can I be guided through how to use it properly here? Thank You.
Here's my API_manager.dart file:
import 'package:http/http.dart' as http;
import 'package:aritic/models/contactsModel.dart';
// ignore: camel_case_types
class API_Manager {
Future<ContactsModel> getContacts() async {
var client = http.Client();
var contactsModel;
String contacts_url =
'https://exampleapi.com';
String basicAuth = 'Basic auth key example';
try {
var response = await client.get(contacts_url,
headers: <String, String>{'authorization': basicAuth});
print(response.statusCode);
if (response.statusCode == 200) {
var jsonString = response.body;
var jsonMap = json.decode(jsonString);
contactsModel = ContactsModel.fromJson(jsonMap);
}
} catch (Exception) {
return contactsModel;
}
return contactsModel;
}
}
My UI Code:
import 'package:aritic/models/contactsModel.dart';
import 'package:aritic/services/api_manager.dart';
class ContactsPage extends StatefulWidget {
#override
_ContactsPageState createState() => _ContactsPageState();
}
class _ContactsPageState extends State<ContactsPage>
with SingleTickerProviderStateMixin {
Future<ContactsModel> _contactsModel;
TabController _tabController;
#override
void initState() {
// TODO: implement initState
super.initState();
_tabController = TabController(length: 2, initialIndex: 0, vsync: this);
_tabController.addListener(_handleTabIndex);
_contactsModel = API_Manager().getContacts();
}
#override
void dispose() {
_tabController.removeListener(_handleTabIndex);
_tabController.dispose();
super.dispose();
}
void _handleTabIndex() {
setState(() {});
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title: Text('Contacts'),
bottom: PreferredSize(
child: Align(
alignment: Alignment.centerLeft,
child: TabBar(
controller: _tabController,
isScrollable: true,
unselectedLabelColor: Colors.white.withOpacity(0.3),
indicatorColor: Colors.white,
tabs: [
Tab(
child: Text('Contacts'),
),
Tab(
child: Text('Companies'),
)
],
),
),
preferredSize: Size.fromHeight(40.0)),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 16.0),
child: IconButton(
icon: Icon(Icons.search),
color: Colors.white,
onPressed: () {},
),
),
],
),
body: TabBarView(controller: _tabController, children: <Widget>[
Container(
height: double.infinity,
child: FutureBuilder<ContactsModel>(
future: _contactsModel,
builder: (BuildContext context,
AsyncSnapshot<ContactsModel> snapshot) {
if (snapshot.hasData) {
return ListView.separated(
shrinkWrap: true,
padding: const EdgeInsets.all(6),
itemCount: snapshot.data.contacts.length,
itemBuilder: (BuildContext context, int index) {
List keys = snapshot.data.contacts.keys.toList();
List values =
snapshot.data.contacts.values.toList();
var contact = values[index];
return InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => ViewContact()));
},
child: Container(
height: 50,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
contact.owner.firstName +
" " +
contact.owner.lastName,
style: TextStyle(fontSize: 16),
),
Text(
contact.owner.username,
style: TextStyle(fontSize: 14),
),
SizedBox(
height: 5,
),
],
),
),
);
},
separatorBuilder: (BuildContext context, int index) {
return SizedBox(
height: 5,
);
},
);
} else
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.blueGrey[700],
valueColor: AlwaysStoppedAnimation<Color>(
Colors.cyan)));
})),
Container(
height: double.infinity,
child: ListView(
padding: const EdgeInsets.all(6),
children: <Widget>[
InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => ViewCompany()));
},
child: Container(
height: 50,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'example company name',
style: TextStyle(fontSize: 16),
),
Text(
'example company domain',
style: TextStyle(fontSize: 14),
)
],
),
),
),
SizedBox(
height: 5,
),
InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => ViewCompany()));
},
child: Container(
height: 50,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'example company name',
style: TextStyle(fontSize: 16),
),
Text(
'example company domain',
style: TextStyle(fontSize: 14),
)
],
),
),
),
],
)),
]),
floatingActionButton: _bottomButtons(),
));
}
Widget _bottomButtons() {
return _tabController.index == 0
? FloatingActionButton(
shape: StadiumBorder(),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return AddContacts();
}));
},
backgroundColor: Colors.cyan,
child: Icon(
Icons.person_add,
color: Colors.white,
))
: FloatingActionButton(
shape: StadiumBorder(),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return AddCompany();
}));
},
backgroundColor: Colors.cyan,
child: Icon(
Icons.add,
color: Colors.white,
),
);
}
}
Json sample(complete json too big to upload here):
{
"total": "187144",
"contacts": {
"897": {
"isPublished": true,
"id": 897,
"fields": {
"core": {
"points": {
"id": "47",
"label": "Points"
},
"firstname": {
"id": "2",
"label": "First Name",
"value": "Jason"
},
"lastname": {
"id": "3",
"label": "Last Name",
"value": "Lamuda"
},
"...": {
"..." : "..."
}
},
"ipAddresses": [
{
"ip": "70.127.91.131",
"ipDetails": {
"city": "Bradenton",
"region": "Florida",
"timezone": "America/New_York",
}
},
"...": {
"..." : "..."
}
Output Screen(stuck on CircularProgressIndicator): here
create a function like
Future getContacts()async{
_contactsModel = API_Manager().getContacts();
}
then inside your initState
getContacts().then((value){
setState((){});
})

Flutter i want to display the data after searching

listviewGood day do you have an idea on how to make a search bar that do not show first the list view when no one searching my data is from mysql sorry new at flutter
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('New Transaction'),
backgroundColor: Color(0xff083663),
),
body: RefreshIndicator(
onRefresh: fetchNotes,
key: _refresh,
child: loading
? Center(
child: CircularProgressIndicator(),
)
: ListView.builder(
itemBuilder: (context, i) {
return i == 0 ? _searchBar() : _listItem(i - 1);
},
itemCount: _notesForDisplay.length + 1,
),
));
}
This is my search bar where the user will input his/her search
_searchBar() {
return Container(
padding: const EdgeInsets.all(10.0),
child: Card(
child: ListTile(
leading: Icon(Icons.search),
title: TextField(
decoration:
InputDecoration(hintText: "Search", border: InputBorder.none),
onChanged: (text) {
text = text.toLowerCase();
setState(() {
_notesForDisplay = _notes.where((note) {
var noTitle = note.vesselname.toLowerCase();
return noTitle.contains(text);
}).toList();
});
},
),
),
),
);
}
this is the list view for my search i want this to show after the user inputted a value in the search bar
_listItem(i) {
final x = _notesForDisplay[i];
return Container(
padding: EdgeInsets.all(20.0),
child: Row(
children: <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Vessel Name:\t' + x.vesselname,
style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold),
),
Text('Voyage #:\t' + x.voyageno,
style: TextStyle(fontSize: 18.0)),
Text('Ship Call #:\t' + x.scn,
style: TextStyle(fontSize: 18.0)),
Divider()
],
),
),
IconButton(
icon: Icon(
Icons.add_circle_outline,
size: 30.0,
),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => Transaction(x)));
}),
],
),
);
}
}
Define a bool variable that indicate the visibility state of the list view:
bool _isListViewVisible = false;
Add it to the setState code block:
setState(() {
_isListViewVisible = true; //Or you can check the text length
_notesForDisplay = _notes.where((note) {
var noTitle = note.vesselname.toLowerCase();
return noTitle.contains(text);
}).toList();
});
Then put the list in a visibility widget:
return Visibility(
visible: _isListViewVisible,
child: Container(
padding: EdgeInsets.all(20.0),
child: Row(
children: <Widget>[
....
],
),
));

How to improve the performance of my app in flutter

I am building an app called LiveTv which is an app which recommends videos as per varied interests.The code I have written is causing serious lags and as I am proceeding more and more in this app it is becoming next to inoperable.I have included the video of the same in this link https://youtu.be/YQp3E3Lukfk
What I have done is make the call async and I have used a ternary operator wherein which under it loads a circular progress indicator is shown.But it doesn't seems to work only
I have included the code which is the one which is controlled by the bottom navigation bar.The services part of it is not included as its function is only to load the data or the object,but I will include one or two so that you may understand and I dont want to make this question very long
class LiveTvHomePage extends StatefulWidget {
final String title;
LiveTvHomePage({
this.title,
});
#override
_LiveTvHomePageState createState() => _LiveTvHomePageState();
}
class _LiveTvHomePageState extends State<LiveTvHomePage> {
//GlobalKey<ScaffoldState> _drawerKey = GlobalKey<ScaffoldState>();
#override
void initState() {
// TODO: implement initState
super.initState();
handleScroll(); // function which is responsible for updating the isScrollingDown variable whenever the user scrolls down
_services();
setState(() {
_isLoading = false;
});
}
_loadingImage() {
return CircularProgressIndicator();
}
_services() {
Services.loadDataForMovieId().then((movieIdList) {
setState(() {
_homeBannerObjectMovieIdList = movieIdList;
});
});
Services.loadDataForMovieIdofPopularMovieSection().then((movieIdList) {
setState(() {
_popularMoviesMovieId = movieIdList;
});
});
Services.loadDataForPopularTvShowSection().then((homePageSeriesPosterList) {
setState(() {
_seriesData = homePageSeriesPosterList;
});
});
Services.loadDataForMusicSection().then((musicList) {
setState(() {
_musicCategories = musicList;
});
});
Services.loadDataForPlaylistTitle().then((title) {
setState(() {
_musicPlaylistThemeName = title;
});
});
Services.loadDataForPopularNewsChannelsNames().then((nameList) {
setState(() {
_popularNewsChannelNames = nameList;
});
});
Services.loadDataForPopularNewsChannelsProfilePicUrls().then((urllist) {
setState(() {
_popularNewsChannelProfilePicUrl = urllist;
});
});
Services.loadDataForLiveNewsChannelsProfilePicUrls().then((urllist) {
setState(() {
_liveNewsChannelProfilePicUrl = urllist;
});
});
Services.loadDataForLiveNewsChannelsNames().then((nameList) {
setState(() {
_liveNewsChannelNames = nameList;
});
});
Services.loadDataForPicOfLatestNews().then((nameList) {
setState(() {
_latestNewsProfilePics = nameList;
});
});
Services.loadDataForOfLatestNewsTitle().then((nameList) {
setState(() {
_latestNewsNewsTitle = nameList;
});
});
Services.loadDataForOfLatestNewsDescription().then((nameList) {
setState(() {
_latestNewsDescription = nameList;
});
});
}
_buildBody(var boxHeight, List<String> youtubeIdUrls) {
return Column(
children: <Widget>[
Stack(
children: <Widget>[
_buildPageView(boxHeight, youtubeIdUrls),
_buildCircleIndicator(youtubeIdUrls),
],
),
],
);
}
_buildPageView(var boxHeight, List<String> youtubeIdUrls) {
return Container(
color: Colors.black87,
height: boxHeight,
child: PageView.builder(
itemCount: 8,
controller: _pageController,
itemBuilder: (BuildContext context, int index) {
try {
// HomeBanner homeBanner=_homeBannelList[index];
return FadeInImage.assetNetwork(
image:
'https://img.youtube.com/vi/${youtubeIdUrls[index].substring(8)}/0.jpg',
placeholder: 'assets/loading.gif',
fit: BoxFit.fill,
);
} catch (e) {
return CircularProgressIndicator();
}
//before return Image.network('https://img.youtube.com/vi/${videoIdOfUrlList[index]}/0.jpg',fit: BoxFit.fill,);
},
onPageChanged: (int index) {
_currentPageNotifier.value = index;
}),
);
}
_buildCircleIndicator(List<String> youtubeIdUrls) {
return Positioned(
left: 0.0,
right: 0.0,
bottom: 0.0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: CirclePageIndicator(
itemCount: 8,
currentPageNotifier: _currentPageNotifier,
),
),
);
}
Widget imageDisplayed(String picUrl) {
return Row(
children: <Widget>[
const SizedBox(
width: 10,
),
CircleAvatar(
backgroundImage: NetworkImage(picUrl),
radius: MediaQuery.of(context).size.height * 0.08,
backgroundColor: Colors.black,
),
const SizedBox(
width: 10,
),
],
);
}
Widget HorizontalListViewWitCircularCards(
String title, List<String> urlList, List<String> nameList) {
return Container(
color: Colors.black,
height: MediaQuery.of(context).size.height * 0.32,
width: MediaQuery.of(context).size.width,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height * 0.07,
color: Colors.black,
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 0, 0),
child: Text(
title,
style: TextStyle(fontSize: 16, color: Colors.white),
),
),
),
Container(
height: MediaQuery.of(context).size.height * 0.23,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: _popularNewsChannelNames.length,
itemBuilder: (BuildContext context, int index) => Card(
color: Colors.black,
child: Padding(
padding: const EdgeInsets.symmetric(),
child: Column(
children: <Widget>[
imageDisplayed(urlList[index]),
const SizedBox(
height: 13,
),
Text(
nameList[index],
style: TextStyle(color: Colors.white),
),
],
),
),
),
),
),
],
),
);
}
Widget HorizontalGridViewOfCardsofGradientColor(int count, List<String> lst) {
return Container(
color: Colors.black,
height: MediaQuery.of(context).size.height * 0.125 * count,
child: GridView.count(
scrollDirection: Axis.horizontal,
crossAxisCount: count,
shrinkWrap: true,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
children: List.generate(20, (index) {
return Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.black,
),
borderRadius: BorderRadius.all(Radius.circular(15)),
gradient: LinearGradient(colors: colorsForCardinMusicPage[index]),
),
child: Center(
child: Text(
lst[index],
),
),
);
}),
),
);
}
Widget HorizontalGridViewOfCardsofGradientColorWithtitle(
int count, String title) {
return Column(
);
}
Widget HorizontalListViewOfButtons(List moviesPageButtonNames) {
return Container(
color: Colors.black,
height: MediaQuery.of(context).size.height * 0.13,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: moviesPageButtonNames.length,
itemBuilder: (BuildContext context, int index) => Row(
children: <Widget>[
SizedBox(
width: 7,
),
FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: BorderSide(color: Colors.grey)),
color: Colors.grey[800],
textColor: Colors.white,
onPressed: () {},
child: Text(moviesPageButtonNames[index]),
),
SizedBox(
width: 10,
)
],
),
),
);
}
Widget NewsPageOfBottomNavigator() {
ServicesForNewsPage.loadObjectList().then((newsPageObject) {
_newsPage = newsPageObject;
});
for (var obj in _newsPage.liveChannels) {
_newsPageLiveNewsUrls.add(obj.publisherProfilePic);
_newsPageChannelName.add(obj.publisherName);
}
// print("_newsPageLiveNewsUrls");
// print(_newsPageLiveNewsUrls);
// print("_newsPageLiveNewsNames");
// print(_newsPageChannelName);`
for (var obj in _newsPage.news) {
_newsPagePopularNewsChannelUrls.add(obj.publishers.profilePicUrl);
_newsPagePopularNewsChannelNames.add(obj.publishers.fullName);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
HorizontalListViewWithoutViewAllForLiveNewsChannels(
"Watch Live", _newsPageLiveNewsUrls, _newsPageChannelName),
HorizontalListViewWitCircularCards("Popular News Channel",
_newsPagePopularNewsChannelUrls, _newsPagePopularNewsChannelNames),
VerticalListView(_newsPagePopularNewsChannelNames, true),
],
);
}
Widget LifeStylePageOfBottomNavigator() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
HorizontalListViewWitCircularCards(
"Popular Lifestyle channels", [""], [""]),
VerticalListView(["ssss"], false),
],
);
}
Widget SportsPageOfBottomNavigator() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
HorizontalListViewWitCircularCards(
"Popular Sports channels", [""], [""]),
VerticalListView(["ssss"], false),
],
);
}
Widget returnToTopButton() {
return Visibility(
visible: _showButton,
child: FlatButton(
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.fromLTRB(0, 7, 0, 0),
child: Text(
"^",
style: TextStyle(color: Colors.white, fontSize: 27),
),
),
Text(
" Return to top",
style: TextStyle(color: Colors.white),
),
],
),
onPressed: () {
_scrollController.animateTo(0,
duration: Duration(milliseconds: 500), curve: Curves.easeInOut);
},
color: Colors.red,
),
);
}
void showFloationButton() {
setState(() {
_showButton = true;
});
}
void hideFloationButton() {
setState(() {
_showButton = false;
});
}
void handleScroll() async {
// or something else..
_scrollController.addListener(() {
double currentScroll = _scrollController.position.pixels;
double delta = MediaQuery.of(context).size.height;
// print("Current scroll position is ..........$currentScroll");
// print("delta pixel is ..........$delta");
if (currentScroll >= delta) {
showFloationButton();
} else if (currentScroll <= delta) {
hideFloationButton();
}
});
}
#override
void dispose() {
// TODO: implement dispose
_scrollController.removeListener(() {});
super.dispose();
}
#override
Widget build(BuildContext context) {
List<Widget> wdgs_option = [
HomePageForBottomNavigator(),
MoviesPageForBottomNavigator(),
TvSHowsPageOfBottomNavigator(),
MusicPageofBottomNavigator(),
// NewsPageOfBottomNavigator(), //dummy for now
NewsPageOfBottomNavigator(),
LifeStylePageOfBottomNavigator(),
SportsPageOfBottomNavigator()
];
return _isLoading
? _loadingImage()
: Scaffold(
// key: _drawerKey,
appBar: AppBar(
automaticallyImplyLeading: false,
leading: Icon(
Icons.live_tv,
color: Colors.amber,
),
backgroundColor: Colors.black,
title: Text(
widget.title,
style: TextStyle(fontSize: 17, color: Colors.amber),
),
actions: <Widget>[
IconButton(
tooltip: 'Search',
icon: const Icon(Icons.search),
onPressed: () {},
),
IconButton(
icon: Icon(
MaterialCommunityIcons.xbox_controller_menu,
color: Colors.white,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DrawerWidget()),
);
},
)
],
),
body: SafeArea(
child: SingleChildScrollView(
controller: _scrollController,
child: wdgs_option.elementAt(_selectedIndex),
),
),
drawer: Drawer(),
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.black,
showUnselectedLabels: true,
type: BottomNavigationBarType.shifting,
currentIndex: _selectedIndex,
fixedColor: Colors.amber,
onTap: _onItemTapped,
items: const <BottomNavigationBarItem>[
// Icon(
// FontAwesome.facebook_square,
// color: Colors.amber,
// ),
BottomNavigationBarItem(
backgroundColor: Colors.black,
icon: Icon(Icons.home),
title: Text('Home'),
),
BottomNavigationBarItem(
backgroundColor: Colors.black,
icon: Icon(
MaterialCommunityIcons.video_vintage,
),
title: Text(
'Movies',
),
),
BottomNavigationBarItem(
backgroundColor: Colors.black,
icon: Icon(Icons.live_tv),
title: Text(
'Tv shows',
),
),
BottomNavigationBarItem(
backgroundColor: Colors.black,
icon: Icon(Icons.music_video),
title: Text(
'Music',
),
),
// BottomNavigationBarItem(
// backgroundColor: Colors.black,
// icon: Icon(Icons.dehaze),
// title: Text(
// 'More',
// ),
// ),
BottomNavigationBarItem(
backgroundColor: Colors.black,
icon: Icon(Icons.radio),
title: Text(
'News',
),
),
BottomNavigationBarItem(
backgroundColor: Colors.black,
icon: Icon(
FontAwesome.heartbeat,
),
title: Text(
'LifeStyle',
),
),
BottomNavigationBarItem(
backgroundColor: Colors.black,
icon: Icon(
Ionicons.md_football,
),
title: Text(
'Sports',
),
),
],
),
);
}
}
The services class seems like this in most cases:
class ServicesForNewsPage {
static const String url =
"https://livetvapi.apyhi.com/api/v3/home?pageLocation=News&countries=IN&app_version=13&"
"user_id=44edc2c905ae163f&package_id=livetv.movies.freemovies.watchtv.tvshows&os_platform=android";
static Future<NewsPage> loadObjectList() async {
var res = await http
.get(url, headers: {'Authorization': dartJsonWebTokenGenerator()});
if (res.statusCode == 200) {
// print("response is there for news Page");
final newsPageObjectList = newsPageFromJson(res.body);
return newsPageObjectList;
} else {
print("no response");
return null;
}
}
}
I am quite new to flutter and things are bit hazy as to how to improve the response time.
You're question is quite broad. Have you tried playing with the DevTools?
I don't know the full code of your project, but I think I see that you are initializing all pages every time the build() of your homepage is called.
Consider changing this:
List<Widget> wdgs_option = [
HomePageForBottomNavigator(),
MoviesPageForBottomNavigator(),
TvSHowsPageOfBottomNavigator(),
MusicPageofBottomNavigator(),
// NewsPageOfBottomNavigator(), //dummy for now
NewsPageOfBottomNavigator(),
LifeStylePageOfBottomNavigator(),
SportsPageOfBottomNavigator()
];
to something either 1.:
if (_selectedIndex == 0) {
wdgs_option = HomePageForBottomNavigator();
} else if (hi == _selectedIndex) {
wdgs_option = MoviesPageForBottomNavigator();
} else if (){}
or to 2.:
List<int Function()> wdgs_option = [
() => HomePageForBottomNavigator(),
() => MoviesPageForBottomNavigator(),
() => ...
];
int val = c[1]();
and in that case
SingleChildScrollView(
controller: _scrollController,
child: wdgs_option.elementAt(_selectedIndex),
)
to
SingleChildScrollView(
controller: _scrollController,
child: wdgs_option[_selectedIndex](),
)

"The method '[]' was called on null" in flutter app and the data is not getting displayed

I have been trying to display data on my flutter app by importing json file in my firebase account but i think there is some error in my code.
class MatchList{
List<MatchListItem> matchList;
MatchList({this.matchList});
factory MatchList.fromJSON(Map<dynamic,dynamic> json){
return MatchList(
matchList: parsematches(json)
);
}
static List<MatchListItem> parsematches(matchJSON){
var mList=matchJSON['browseMatches'] as List;
List<MatchListItem> matchList=mList.map((data) => MatchListItem.fromJson(data)).toList();
return matchList;
}
}
class MatchListItem {
int id;
String title;
String match;
String date;
String desc;
MatchListItem({this.id,this.title,this.match,this.date,this.desc});
factory MatchListItem.fromJson(Map<dynamic,dynamic> parsedJson) {
// print(parsedJson);
return MatchListItem(id: parsedJson['index'],title:parsedJson['title'],match: parsedJson['match'],date:parsedJson['date'],desc:parsedJson['desc']);
}
}
This is my matchListModel.dart file
import 'package:firebase_database/firebase_database.dart';
import 'package:nostra_prediction/matchListModel.dart';
import 'dart:async' show Future;
class MakeCall{
List<MatchListItem> listItems=[];
// ListItem recipeModelList=new ListItem();
Future<List<MatchListItem>> firebaseCalls (DatabaseReference databaseReference) async{
MatchList matchList;
DataSnapshot dataSnapshot = await databaseReference.once();
Map<dynamic,dynamic> jsonResponse=dataSnapshot.value[0]['content'];
matchList = new MatchList.fromJSON(jsonResponse);
print(matchList);
listItems.addAll(matchList.matchList);
// for(var i in matchList.matchList){
// listItems.addAll(matchList.matchList);
// }
// print(matchList.matchList[1].foodtitle);
print('Thatt ${listItems[0].title}');
// return matchList.matchList;
return listItems;
}
}
This is my getMainListInformation.dart file
import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:nostra_prediction/constants.dart';
import 'package:nostra_prediction/getMainListInformation.dart';
class Matches extends StatefulWidget{
#override
MatchesList createState()=> MatchesList();
}
class MatchesList extends State<Matches>{
final color = const Color(0xffbfd6ba);
final colorText = const Color(0xffd1bad6);
final databaseReference = FirebaseDatabase.instance.reference();
final makecall= new MakeCall();
#override
Widget build(BuildContext context) {
var futureBuilder=new FutureBuilder(
future: makecall.firebaseCalls(databaseReference), // async work
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none: return new Text('Press button to start');
case ConnectionState.waiting: return new Text('Loading....');
default:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
return
ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index){
// return new Text(snapshot.data[index].foodtitle);
return Card(
elevation: 0.0,
child: Padding(
padding: const EdgeInsets.all(0.0),
child: SizedBox(
height: MediaQuery.of(context).size.height*0.15,
width: MediaQuery.of(context).size.width,
child: Card(
elevation: 0,
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 10,right: 5,top: 5),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(snapshot.data[index].title, style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20,fontFamily: 'Roboto-Black'),),
SizedBox(height:10.0),
Row(
children: <Widget>[
new IconTheme(
data: new IconThemeData(
color: Colors.black26),
child: new Icon(Icons.timer,size: 20.0,),
),
Text('${snapshot.data[index].match} minutes',style: TextStyle(fontWeight: FontWeight.w700,color: Colors.black26),)
],
)
],
)
],
),
),
// rightFavFood
],
),
)
],
)
)
),
),
);
},
);
}
},
);
return Scaffold(
resizeToAvoidBottomPadding: false,
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: color,
centerTitle: true,
// title: Text('Browsing', style: TextStyle(fontFamily: 'Roboto-Black',fontSize: 25,fontWeight: FontWeight.w500,color: Colors.black),),
title : new Image.asset('images/cooking.png'),
actions: <Widget>[
IconButton(icon: Icon(Icons.menu), color: Colors.black26,onPressed: (){print('Menu pressed');},)
],
elevation: 0.0,
),
body: new Column(
children: <Widget>[
new Container(
padding: EdgeInsets.only(top: 5.0,bottom: 10),
color: color,
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ButtonTheme(
minWidth: MediaQuery.of(context).size.width*0.4,
height: MediaQuery.of(context).size.height*0.06,
child:MaterialButton(
onPressed: (){
// MakeCall makecall= new MakeCall();
// var response=makecall.firebaseCalls(databaseReference);
// print(makecall.listItems[0].foodtitle);
// print(makecall.listItems[1].foodtitle);
// new ListView.builder(
// itemCount: makecall.listItems.length,
// itemBuilder: (BuildContext context, int index){
// return
// },
// );
},
color: Colors.white,
// disabledTextColor: Colors.grey,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.horizontal(left: Radius.circular(10.0), right: Radius.circular(1.0))
),
// elevation: 15.0,
splashColor: color,
highlightColor:color,
// highlightElevation: 1.0,
child: Text("Cook Book",style: TextStyle(fontFamily: 'Roboto-Thin ',color: Colors.black26,fontSize: 15),),
) ,
),
ButtonTheme(
minWidth: MediaQuery.of(context).size.width*0.4,
height: MediaQuery.of(context).size.height*0.06,
buttonColor: Colors.amberAccent,
child:MaterialButton(
onPressed: (){Scaffold.of(context).showSnackBar(SnackBar(content: Text('Hey There')));},
color: Colors.white,
// disabledTextColor: Colors.grey,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.horizontal(right: Radius.circular(10.0), left: Radius.circular(1.0))
),
// elevation: 15.0,
highlightColor:color,
// highlightElevation: 1.0,
child: Text("Favourite",style: TextStyle(fontFamily: 'Roboto-Thin ',color: Colors.black26,fontSize: 15)),
) ,
),
],
),
),
SizedBox(height: 0),
new Expanded(
//
child:Container(
child: futureBuilder,
) ,
//
),
],
),
bottomNavigationBar: BottomNavigationBar(
backgroundColor: color,
elevation: 20.0,
currentIndex: 0,
items: [
BottomNavigationBarItem(
icon: new Icon(Icons.home,color: Colors.white,),
title: new Text('Home',style: TextStyle(color: Colors.white,fontWeight: FontWeight.w700)),
),
BottomNavigationBarItem(
icon: new Icon(Icons.add_circle,color: Colors.white,),
title: new Text('Add a Recipe',style: TextStyle(color: Colors.white,fontWeight: FontWeight.w700))
),
BottomNavigationBarItem(
icon: new Icon(Icons.collections,color: Colors.white,),
title: new Text('My recipes',style: TextStyle(color: Colors.white,fontWeight: FontWeight.w700),),
)
],
),
);
}
}
this is my body.dart file
{
"json": [{
"content": {
"browseMatches": [{
"index": 1,
"date" : "12/04/12",
"desc" : "asdfgh",
"match": "abcdefgh",
"title": "wxyz"
}, {
"index": 12,
"date" : "12/04/12",
"desc" : "qwerty",
"match": "abcd",
"title": "xyz"
}
]
}
}]
}
And lastly this is my json data.
I have been trying to display this json data in a listview on card but unable to do so.Please help!
the exact message which gets displayed is:
Error:NoSuchMethodFound.The method '[]' was called on null.
Receiver:null
Tried calling: