Error when pulling data from firestore using streambuilder - firebase

I am trying to pull data from my firestore database using flutter but am getting the below error:
type 'String' is not a subtype of type 'ImageProvider'
I am using stream builder and have defined the class but it does not seem to be recognising the image that I need to pull. Below is all the code I have used for my stream builder.
firestore database
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:ui' as ui;
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Profile Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Profile'),
);
}
}
class Photo {
final int photourl;
final DocumentReference reference;
Photo.fromMap(Map<String, dynamic> map, {this.reference})
: photourl = map['photourl'];
Photo.fromSnapshot(DocumentSnapshot snapshot)
: this.fromMap(snapshot.data, reference: snapshot.reference);
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
final _width = MediaQuery.of(context).size.width;
final _height = MediaQuery.of(context).size.height;
return StreamBuilder<DocumentSnapshot>(
stream: Firestore.instance
.collection('users')
.document('testuser')
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Stack(
children: <Widget>[
new Container(
color: Colors.blue,
),
new Image.network(
snapshot.data['photourl'].toString(),
fit: BoxFit.fill,
),
new BackdropFilter(
filter: new ui.ImageFilter.blur(
sigmaX: 6.0,
sigmaY: 6.0,
),
child: new Container(
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.9),
borderRadius: BorderRadius.all(Radius.circular(50.0)),
),
)),
new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
centerTitle: false,
elevation: 0.0,
backgroundColor: Colors.transparent,
),
drawer: new Drawer(
child: new Container(),
),
backgroundColor: Colors.transparent,
body: new Center(
child: new Column(
children: <Widget>[
new SizedBox(
height: _height / 12,
),
new CircleAvatar(
radius: _width < _height ? _width / 4 : _height / 4,
backgroundImage: snapshot.data['photourl'],
),
new SizedBox(
height: _height / 25.0,
),
new Text(
snapshot.data['name'],
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: _width / 15,
color: Colors.white),
),
new Padding(
padding: new EdgeInsets.only(
top: _height / 30,
left: _width / 8,
right: _width / 8),
),
new Divider(
height: _height / 15,
color: Colors.white,
),
new Row(
children: <Widget>[
rowCell(
snapshot.data['totalquestions'], 'Answers'),
rowCell('£ 673826', 'Earned'),
],
),
new Divider(
height: _height / 15, color: Colors.white),
],
),
))
],
);
} else {
return CircularProgressIndicator();
}
});
}

Inside your Column widget, you have included a CircleAvatar and passed in a wrong parameter to the backgroundImage property. backgroundImage takes an ImageProvider rather than a String of the photo url.
you should change this:
CircleAvatar(
radius: _width < _height ? _width / 4 : _height / 4,
backgroundImage: snapshot.data['photourl'],
),
to this:
CircleAvatar(
radius: _width < _height ? _width / 4 : _height / 4,
backgroundImage: NetworkImage(snapshot.data['photourl']),
),

Related

How to get pedometer(stepcountvalue) data on Autoupdate basis from firestore

I want to retrieve StepCountValue from firestore and display it to my app on realtimeAutoupdate basis. RealtimeAutoupdate basis means i want a realtime/without refreshing method.So, if a user cover some distance then he/she gets his/her total walking steps in app.
How to retrieve data from database and throw it in a container(page.dart)
How to get pedometer(stepcountvalue) automatic changing data on Autoupdate and retrieve
With firestore
How to update this data to firestore automatically
This is my main.dart
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_testing/models/brew.dart';
import 'package:flutter_testing/models/user.dart';
import 'package:flutter_testing/screens/Pages/page.dart';
import 'package:flutter_testing/screens/wrapper.dart';
import 'package:flutter_testing/services/auth.dart';
import 'package:flutter_testing/services/database.dart';
import 'dart:async';
import 'package:percent_indicator/circular_percent_indicator.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:pedometer/pedometer.dart';
import 'package:provider/provider.dart';
void main() => runApp(new NewApp());
class NewApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamProvider<User>.value(
value: AuthService().user,
child: MaterialApp(
home: Wrapper(),
),
);
}
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final AuthService _auth = AuthService();
String muestrePasos = "";
String _km = "Unknown";
String _calories = "Unknown";
String stepCountValue = 'Unknown';
String _showcoin = '0';
StreamSubscription<int> _subscription;
double _numerox; //numero pasos
double _convert;
double _kmx;
double burnedx;
double _coin;
double _porciento;
// double percent=0.1;
#override
void initState() {
super.initState();
//initPlatformState();
setUpPedometer();
}
//inicia codigo pedometer
void setUpPedometer() {
Pedometer pedometer = new Pedometer();
_subscription = pedometer.stepCountStream.listen(_onData,
onError: _onError, onDone: _onDone, cancelOnError: true);
}
void _onData(int stepCountValue1) async {
// print(stepCountValue); //impresion numero pasos por consola
setState(() {
stepCountValue = "$stepCountValue1";
// print(stepCountValue);
});
var dist = stepCountValue1; //pasamos el entero a una variable llamada dist
double y = (dist + .0); //lo convertimos a double una forma de varias
setState(() {
_numerox = y; //lo pasamos a un estado para ser capturado ya convertido a double
});
var long3 = (_numerox);
long3 = num.parse(y.toStringAsFixed(2));
var long4 = (long3 / 10000);
int decimals = 1;
int fac = pow(10, decimals);
double d = long4;
d = (d * fac).round() / fac;
print("d: $d");
getDistanceRun(_numerox);
setState(() {
_convert = d;
print(_convert);
});
}
void reset() {
setState(() {
int stepCountValue1 = 0;
stepCountValue1 = 0;
stepCountValue = "$stepCountValue1";
});
}
void _onDone() {}
void _onError(error) {
print("Flutter Pedometer Error: $error");
}
//function to determine the distance run in kilometers using number of steps
void getDistanceRun(double _numerox) {
var distance = ((_numerox * 76) / 100000);
distance = num.parse(distance.toStringAsFixed(2)); //dos decimales
var distancekmx = distance * 34;
distancekmx = num.parse(distancekmx.toStringAsFixed(2));
//print(distance.runtimeType);
var coiny = ((_numerox * 125) / 100000);
coiny = num.parse(coiny.toStringAsFixed(2));
setState(() {
_km = "$distance";
//print(_km);
});
setState(() {
_kmx = num.parse(distancekmx.toStringAsFixed(2));
});
setState(() {
_coin = num.parse(coiny.toStringAsFixed(2));
//print(_coiny);
});
}
//function to determine the calories burned in kilometers using number of steps
void getBurnedRun() {
setState(() {
var calories = _kmx; //dos decimales
_calories = "$calories";
//print(_calories);
});
}
void coins() {
setState(() {
var showcoin = _coin;
_showcoin = "$showcoin";
});
}
//fin codigo pedometer
#override
Widget build(BuildContext context) {
//print(_stepCountValue);
getBurnedRun();
coins();
return StreamProvider<QuerySnapshot>.value(
value: DatabaseService().step,
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: new Scaffold(
appBar: new AppBar(
title: const Text('Step Counter'),
backgroundColor: Colors.black54,
actions: <Widget>[
FlatButton.icon(
icon: Icon(Icons.person),
label: Text('logout'),
onPressed: () async {
await _auth.signOut();
}
),
FlatButton.icon(
icon: Icon(Icons.arrow_back),
label: Text('New Page'),
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => pages()));
}
),
],
),
body: new ListView(
padding: EdgeInsets.all(5.0),
children: <Widget>[
Container(
padding: EdgeInsets.only(top: 10.0),
width: 250,
//ancho
height: 250,
//largo tambien por numero height: 300
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment
.bottomCenter, //cambia la iluminacion del degradado
end: Alignment.topCenter,
colors: [Color(0xFFA9F5F2), Color(0xFF01DFD7)],
),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(27.0),
bottomRight: Radius.circular(27.0),
topLeft: Radius.circular(27.0),
topRight: Radius.circular(27.0),
)),
child: new CircularPercentIndicator(
radius: 200.0,
lineWidth: 13.0,
animation: true,
center: Container(
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
height: 50,
width: 50,
padding: EdgeInsets.only(left: 20.0),
child: Icon(
FontAwesomeIcons.walking,
size: 30.0,
color: Colors.white,
),
),
Container(
//color: Colors.orange,
child: Text(
'$stepCountValue',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0,
color: Colors.purpleAccent),
),
// height: 50.0,
// width: 50.0,
),
],
),
),
percent: 0.217,
//percent: _convert,
footer: new Text(
"Steps: $stepCountValue",
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 12.0,
color: Colors.purple),
),
circularStrokeCap: CircularStrokeCap.round,
progressColor: Colors.purpleAccent,
),
),
Divider(
height: 5.0,
),
Container(
width: 80,
height: 100,
padding: EdgeInsets.only(left: 25.0, top: 10.0, bottom: 10.0),
color: Colors.transparent,
child: Row(
children: <Widget>[
new Container(
child: new Card(
child: Container(
height: 80.0,
width: 80.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/distance.png"),
fit: BoxFit.fitWidth,
alignment: Alignment.topCenter,
),
),
child: Text(
"$_km Km",
textAlign: TextAlign.right,
style: new TextStyle(
fontWeight: FontWeight.bold, fontSize: 14.0),
),
),
color: Colors.white54,
),
),
VerticalDivider(
width: 20.0,
),
new Container(
child: new Card(
child: Container(
height: 80.0,
width: 80.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/burned.png"),
fit: BoxFit.fitWidth,
alignment: Alignment.topCenter,
),
),
),
color: Colors.transparent,
),
),
VerticalDivider(
width: 20.0,
),
new Container(
child: new Card(
child: Container(
height: 80.0,
width: 80.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/step.png"),
fit: BoxFit.fitWidth,
alignment: Alignment.topCenter,
),
),
),
color: Colors.transparent,
),
),
],
),
),
Divider(
height: 2,
),
Container(
padding: EdgeInsets.only(top: 2.0),
width: 150,
//ancho
height: 30,
//largo tambien por numero height: 300
color: Colors.transparent,
child: Row(
children: <Widget>[
new Container(
padding: EdgeInsets.only(left: 40.0),
child: new Card(
child: Container(
child: Text(
"$_km Km",
textAlign: TextAlign.right,
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14.0,
color: Colors.white),
),
),
color: Colors.purple,
),
),
VerticalDivider(
width: 20.0,
),
new Container(
padding: EdgeInsets.only(left: 10.0),
child: new Card(
child: Container(
child: Text(
"$_calories kCal",
textAlign: TextAlign.right,
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14.0,
color: Colors.white),
),
),
color: Colors.red,
),
),
VerticalDivider(
width: 5.0,
),
new Container(
padding: EdgeInsets.only(left: 10.0),
child: new Card(
child: Container(
child: Text(
"$_showcoin Coins",
textAlign: TextAlign.right,
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14.0,
color: Colors.white),
),
),
color: Colors.black,
),
),
],
),
),
],
),
),
),
);
}
}
this is my wrapper.dart
import 'package:flutter_testing/models/user.dart';
import 'package:flutter_testing/screens/authenticate/authenticate.dart';
import 'package:flutter/material.dart';
import 'package:flutter_testing/main.dart';
import 'package:provider/provider.dart';
class Wrapper extends StatelessWidget {
#override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
// return either the Home or Authenticate widget
if (user == null){
return Authenticate();
} else {
return MyApp();
}
}
}
this is page.dart
import 'package:flutter/material.dart';
import 'package:flutter_testing/main.dart';
class pages extends StatefulWidget {
#override
_pagesState createState() => _pagesState();
}
class _pagesState extends State<pages> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.amber,
appBar: new AppBar(
actions: <Widget>[
FlatButton.icon(
icon: Icon(Icons.arrow_back_ios),
label: Text('back'), onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => MyApp())
);
}
),
],
),
body: Container(),
);
}
}
this is database.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_testing/models/brew.dart';
class DatabaseService {
final String uid;
DatabaseService({ this.uid });
// collection reference
final CollectionReference brewCollection = Firestore.instance.collection('step');
Future<void> updateUserData(int stepCountValue, int _calories, int _km , int _showcoin) async {
return await brewCollection.document(uid).setData({
'stepCountValue': stepCountValue,
'_calories': _calories,
'_km': _km,
'_showcoin': _showcoin,
});
// get brews stream
Stream<QuerySnapshot> get step {
return brewCollection.snapshots();
}
}
this is brew.dart
class Brew {
final int stepCountValue;
Brew({ this.stepCountValue });
}
I hope this is enough to solve my problem. I'm very new to Flutter and I dont know much about firebase and firestore, so it would be nice, if you can say where EXACTLY I have to change WHAT or add WHAT. Thank you so much!!!
You can write a query in the _onData() function of your main.dart file this will update the data automatically whenever there will be any change in your steps. And you can retrieve data in real time using streamBuilder easily.
for example:
void _onData(int stepCountValue1) async {
// print(stepCountValue); //impresion numero pasos por consola
setState(() {
stepCountValue = "$stepCountValue1";
});
final CollectionReference brewCollection = Firestore.instance.collection('step');
await brewCollection.document(uid).setData({
'stepCountValue': stepCountValue,
});
}

How can I Sign up a user on firebase?

I want to sign up a user on firebase that I store in a variable.
Here is my code :
import 'package:flutter/material.dart';
import 'package:login_signup/constants/constants.dart';
import 'package:login_signup/ui/widgets/custom_shape.dart';
import 'package:login_signup/ui/widgets/customappbar.dart';
import 'package:login_signup/ui/widgets/responsive_ui.dart';
import 'package:login_signup/ui/widgets/textformfield.dart';
import 'package:email_validator/email_validator.dart';
class SignUpScreen extends StatefulWidget {
#override
_SignUpScreenState createState() => _SignUpScreenState();
}
class _SignUpScreenState extends State<SignUpScreen> {
bool checkBoxValue = false;
double _height;
double _width;
double _pixelRatio;
bool _large;
bool _medium;
TextEditingController emailEditingController = TextEditingController();
String email;
void validation() {
// email should be instantiated here
email = emailEditingController.text;
bool emailvalidated = EmailValidator.validate(email);
if (emailvalidated) {
print('Email validated');
} else{
print('email not validated');
}
}
Widget clipShape() {
return Stack(
children: <Widget>[
Opacity(
opacity: 0.75,
child: ClipPath(
clipper: CustomShapeClipper(),
child: Container(
height: _large
? _height / 8
: (_medium ? _height / 7 : _height / 6.5),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.orange[200], Colors.pinkAccent],
),
),
),
),
),
Opacity(
opacity: 0.5,
child: ClipPath(
clipper: CustomShapeClipper2(),
child: Container(
height: _large
? _height / 12
: (_medium ? _height / 11 : _height / 10),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.orange[200], Colors.pinkAccent],
),
),
),
),
),
Container(
height: _height / 5.5,
alignment: Alignment.center,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
spreadRadius: 0.0,
color: Colors.black26,
offset: Offset(1.0, 10.0),
blurRadius: 20.0),
],
color: Colors.white,
shape: BoxShape.circle,
),
child: GestureDetector(
onTap: () {
print('Adding photo');
},
child: Icon(
Icons.add_a_photo,
size: _large ? 40 : (_medium ? 33 : 31),
color: Colors.orange[200],
)),
),
],
);
}
Widget form() {
return Container(
margin: EdgeInsets.only(
left: _width / 12.0, right: _width / 12.0, top: _height / 20.0),
child: Form(
child: Column(
children: <Widget>[
firstNameTextFormField(),
SizedBox(height: _height / 60.0),
lastNameTextFormField(),
SizedBox(height: _height / 60.0),
emailTextFormField(),
SizedBox(height: _height / 60.0),
phoneTextFormField(),
SizedBox(height: _height / 60.0),
passwordTextFormField(),
],
),
),
);
}
Widget firstNameTextFormField() {
return CustomTextField(
keyboardType: TextInputType.text,
icon: Icons.person,
hint: "First Name",
);
}
Widget emailTextFormField() {
return CustomTextField(
// assign your email controller to the custom text field here,
keyboardType: TextInputType.emailAddress,
icon: Icons.email,
hint: "Email ID",
textEditingController: emailEditingController,
);
}
Widget acceptTermsTextRow() {
return Container(
margin: EdgeInsets.only(top: _height / 100.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Checkbox(
activeColor: Colors.orange[200],
value: checkBoxValue,
onChanged: (bool newValue) {
setState(() {
checkBoxValue = newValue;
});
}),
Text(
"I accept all terms and conditions",
style: TextStyle(
fontWeight: FontWeight.w400,
fontSize: _large ? 12 : (_medium ? 11 : 10)),
),
],
),
);
}
Widget button() {
return RaisedButton(
elevation: 0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30.0)),
onPressed: () {
validation();
},
padding: const EdgeInsets.all(12.0),
child: Text(
'SIGN UP',
style: TextStyle(fontSize: _large ? 14 : (_medium ? 12 : 10)),
),
),
);
}
I would appreciate your help.
But I need to auto login for my app too and thanks again.
I guess what you are asking is to sign in with firebase to your app using Email and Password.
In that case. The article below covers all what you want.
Sign in with email and password using firebase in flutter.
Sign in with email and password using firebase in flutter
I hope this answers your question.
UPDATED
Here is the link to the Github repository of the article above :
Github Repository

How to store geolocation data in Flutter with Cloud Firestore

I have a problem querying my geolocation data from my database in Cloud Firestore. I went through the documentation on Youtube and came to the conclusion that it will work best for me when i save the geolocation data in subcollections.
Here is my databse structure:
And if you go into one of the documents in the subcollection:
The database itself has a collection called "tourguides", with each document containing basic info like the name of the tour and the region where the tour is (both are Strings). Each of the documents then have a subcollection called "locations", where each document has the Strings "Name" and "ID" and also a geopoint with latitude and longitude data.
The documents from the "Tourguides" collection are shown in a ListView. Whenever i tap on one of the entries, a map shall open where all the markers from the respective subcollection are shown.
Here is my ListView Builder:
#override
void initState() {
super.initState();
_pointsofinterest = Firestore.instance.collection('tourguides').document('sydney_downtown_guide').col lection('locations').orderBy('name').snapshots();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<QuerySnapshot>(
stream: _pointsofinterest,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) return new Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return new Text('Loading...');
default:
return new ListView(
children:
snapshot.data.documents.map((DocumentSnapshot document) {
return InkWell(
child: new ListTile(
title: new Text(document['name']),
subtitle: new Text(document['region']),
onTap: () {
return TourMap(
documents: snapshot.data.documents,
initialPosition: const LatLng(-33.868210, 151.208391),
mapController: _mapController,
);
},
),
);
}).toList(),
);
}
},
),
);
}
I put my map into a StatlessWidget (I am not sure. Maybe this has to be a StatefulWidget?):
class TourMap extends StatelessWidget {
const TourMap({
Key key,
#required this.documents,
#required this.initialPosition,
#required this.mapController,
}) : super(key: key);
final List<DocumentSnapshot> documents;
final LatLng initialPosition;
final Completer<GoogleMapController> mapController;
#override
Widget build(BuildContext context) {
return GoogleMap(
initialCameraPosition: CameraPosition(
target: initialPosition,
zoom: 12,
),
markers: documents
.map((document) => Marker(
markerId: MarkerId(document['placeId']),
icon: BitmapDescriptor.defaultMarker,
position: LatLng(
document['geolocation'].latitude,
document['geolocation'].longitude,
),
infoWindow: InfoWindow(
title: document['location_name'],
),
))
.toSet(),
onMapCreated: (mapController) {
this.mapController.complete(mapController);
},
);
}}
Now i dont exactly know how to set up the query in my OnTap function. The Firestore documentation showed that i always have to refer to specfic documents if i go down the collections from my database.
For example (collection/document/collecion). But in my query, the "document" in the middle of the path is always different, depending on which tourguide the user clicks.
Any ideas on that? Looking Forward to your replies!
UPDATE: I slightly configured my database structure! I now use two seperate databases. One database holds information about the available tourguides (just two Strings currently: Name and Region) and the other stores the actual individual Locations.
I now use where-queries to get the correct locations based on the tourguide´s Name they´re belonging to.
The query itself works on the OnTap function now:
return new ListView(
children:
snapshot.data.documents.map((DocumentSnapshot document) {
return InkWell(
child: new ListTile(
title: new Text(document['name']),
subtitle: new Text(document['region']),
onTap: () {
Firestore.instance.collection('locations').where(
"toActivity",
isEqualTo: document['name'],
)
.snapshots()
.listen((data) =>
data.documents.forEach((doc) => print(doc["location_name"])));
},
),
);
}).toList(),
);
The database structure:
The correct entries are printed into the console if i tap on one of the entries in the ListView. But i will need a Google Map to pop up that shows the appropriate markers based on the "geolocation" values from the database.
Bro, I did. I can retrieve it by two ways.
1. manually by using simple 'initState'.
2. second by using provider (but by using the second method, i have not succeed to show the marker, yet). Hope can help you, although it was long time ago. Here is mine by using 'initState':
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:provider/provider.dart';
import 'package:visitmalang/provider/aktivitas_provider.dart';
import 'package:visitmalang/ui/home/beranda/aktivitas/profil_agen_wisata.dart';
import 'package:visitmalang/ui/widget/textcustom.dart';
class MapAktivitas extends StatefulWidget {
#override
_MapAktivitasState createState() => _MapAktivitasState();
}
class _MapAktivitasState extends State<MapAktivitas> {
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
GoogleMapController mapController;
bool mapToggle = false;
bool geraiToggle = false;
var currentLocation;
var clients = [];
#override
void initState() {
// TODO: implement initState
super.initState();
Geolocator().getCurrentPosition().then((lokasiSekarang) {
setState(() {
currentLocation = lokasiSekarang;
mapToggle = true;
populateClients();
});
});
}
populateClients() {
clients = [];
Firestore.instance.collection('trail').getDocuments().then((docs) {
if (docs.documents.isNotEmpty) {
setState(() {
geraiToggle = true;
});
for (int i = 0; i < docs.documents.length; i++) {
clients.add(docs.documents[i].data);
initMarker(docs.documents[i].data, docs.documents[i].documentID);
}
}
});
}
void initMarker(request, requestId) {
var markerIdVal = requestId;
final MarkerId markerId = MarkerId(markerIdVal);
final Marker marker = Marker(
markerId: markerId,
position: LatLng(
request['koordinat'].latitude, request['koordinat'].longitude),
infoWindow: InfoWindow(title: request['nama']));
setState(() {
markers[markerId] = marker;
});
}
Widget clientCard(client) {
return Padding(
padding: const EdgeInsets.only(left: 8.0, top: 8.0),
child: InkWell(
onTap: () {
zoomInMarker(client);
},
child: Stack(
alignment: FractionalOffset(0.5, 0.94),
children: <Widget>[
Material(
elevation: 4.0,
borderRadius: BorderRadius.circular(10.0),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.white,
),
height: 108,
width: 200,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
//
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
bottomLeft: Radius.circular(10.0)),
child: Container(
width: 96,
height: 108,
child: Image.asset(
'assets/trail.png',
fit: BoxFit.cover,
),
),
),
SizedBox(
width: 4,
),
Stack(
alignment: FractionalOffset(0.5, 0.9),
children: <Widget>[
Container(
width: 100,
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0),
child: Container(
alignment: Alignment.center,
child: textCustom(client['nama'],
Colors.black87, 14, 'Montserrat'),
),
),
],
),
),
),
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: InkWell(
onTap: () => Navigator.of(context).push(
CupertinoPageRoute(
builder: (BuildContext context) =>
ProfilAgenWisata(
nama: client['nama'],
deskripsi: client['deskripsi'],
website: client['website'],
email: client['email'],
noTelepon: client['noTelepon'],
whatsApp: client['whatsApp'],
alamat: client['alamat'],
fasilitas: client['fasilitas'],
))),
child: Container(
alignment: Alignment.center,
color: Color(0xFFDB5C48),
height: 40,
width: 88,
child: textCustom(
'Detail', Colors.white, 14, 'Montserrat'),
),
),
)
],
),
],
),
),
),
],
)),
);
}
zoomInMarker(client) {
mapController.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(
client['koordinat'].latitude, client['koordinat'].longitude),
zoom: 16.0,
bearing: 19.0,
tilt: 15.0),
),
);
}
#override
Widget build(BuildContext context) {
// AktivitasNotifier aktivitasNotifier = Provider.of<AktivitasNotifier>(context);
return Scaffold(
appBar: AppBar(
title: textCustom('Ngetrail', Colors.black87, 18, 'Montserrat'),
centerTitle: true,
elevation: 0.0,
backgroundColor: Colors.transparent.withOpacity(0.0),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios, color: Colors.black87),
onPressed: (){Navigator.pop(context);},),
),
body: Stack(
children: <Widget>[
Column(
children: <Widget>[
Container(
width: double.infinity,
height: MediaQuery.of(context).size.height - 80,
child: mapToggle
? GoogleMap(
myLocationEnabled: true,
myLocationButtonEnabled: true,
markers: Set<Marker>.of(markers.values),
compassEnabled: false,
zoomControlsEnabled: false,
mapType: MapType.normal,
initialCameraPosition: CameraPosition(
target: LatLng(currentLocation.latitude,
currentLocation.longitude),
zoom: 15),
onMapCreated: (controller) {
setState(() {
mapController = controller;
});
},
)
: Center(
child: textCustom(
'Loading...', Colors.black87, 20, 'Hind')),
),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
height: 140.0,
width: MediaQuery.of(context).size.width,
child: geraiToggle
? ListView(
scrollDirection: Axis.horizontal,
padding: EdgeInsets.all(8.0),
children: clients.map((element) {
return clientCard(element);
}).toList(),
)
: Container(),
),
SizedBox(
height: 56.0,
)
],
)
],
));
}
}
Here is the second method, by using provider.
First, you have to decide the model (just focus on 'koordinat'):
class ModelAktivitas {
String idAktivitas;
var koordinat;
String nama;
String deskripsi;
String alamat;
String email;
String noTelepon;
String website;
String gambarUtama;
List galeri;
List fasilitas;
ModelAktivitas.fromMap(Map<String, dynamic> data) {
idAktivitas = data['idAktivitas'];
koordinat = data['koordinat'];
nama = data['nama'];
deskripsi = data['deskripsi'];
noTelepon = data['nomorTelepon'];
galeri = data['galeri'];
fasilitas = data['fasilitas'];
alamat = data['alamat'];
email = data['alamat'];
gambarUtama = data['gambarUtama'];
website = data['website'];
}
}
second, make provider for it:
import 'dart:collection';
import 'package:flutter/cupertino.dart';
import 'package:visitmalang/models/aktivitas_model.dart';
class AktivitasNotifier with ChangeNotifier {
List<ModelAktivitas> _listAktivitas = [];
ModelAktivitas _detailAktivitas;
UnmodifiableListView<ModelAktivitas> get listAktivitas =>
UnmodifiableListView(_listAktivitas);
ModelAktivitas get detailAktivitas => _detailAktivitas;
set listAktivitas(List<ModelAktivitas> listAktivitas) {
_listAktivitas = listAktivitas;
notifyListeners();
}
set detailAktivitas(ModelAktivitas aktivitas) {
_detailAktivitas = aktivitas;
notifyListeners();
}
}
After that, add the "get" from your firestore services:
getListAktivitas(AktivitasNotifier aktivitasNotifier) async {
QuerySnapshot snapshot =
await Firestore.instance.collection('trail').getDocuments();
List<ModelAktivitas> _listAktivitas = [];
snapshot.documents.forEach((doc) {
ModelAktivitas modelAktivitas = ModelAktivitas.fromMap(doc.data);
_listAktivitas.add(modelAktivitas);
});
aktivitasNotifier.listAktivitas = _listAktivitas;
}
then, the last step stream it to your UI code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:provider/provider.dart';
import 'package:visitmalang/provider/aktivitas_provider.dart';
import 'package:visitmalang/ui/home/beranda/aktivitas/profil_agen_wisata.dart';
import 'package:visitmalang/ui/widget/textcustom.dart';
import 'package:visitmalang/service/user_service.dart';
class MapAktivitasTandingan extends StatefulWidget {
#override
_MapAktivitasTandinganState createState() => _MapAktivitasTandinganState();
}
class _MapAktivitasTandinganState extends State<MapAktivitasTandingan> {
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
GoogleMapController mapController;
bool mapToggle = false;
bool geraiToggle = false;
var currentLocation;
#override
void initState() {
// TODO: implement initState
super.initState();
Geolocator().getCurrentPosition().then((lokasiSekarang) {
setState(() {
currentLocation = lokasiSekarang;
mapToggle = true;
});
});
AktivitasNotifier aktivitasNotifier =
Provider.of<AktivitasNotifier>(context, listen: false);
getListAktivitas(aktivitasNotifier);
}
#override
Widget build(BuildContext context) {
AktivitasNotifier aktivitasNotifier =
Provider.of<AktivitasNotifier>(context);
return Scaffold(
appBar: AppBar(
title: textCustom('Ngetrail', Colors.black87, 18, 'Montserrat'),
centerTitle: true,
elevation: 0.0,
backgroundColor: Colors.transparent.withOpacity(0.0),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios, color: Colors.black87),
onPressed: () {
Navigator.pop(context);
},
),
),
body: Stack(
children: <Widget>[
Column(
children: <Widget>[
Container(
width: double.infinity,
height: MediaQuery.of(context).size.height - 80,
child: mapToggle
? GoogleMap(
myLocationEnabled: true,
myLocationButtonEnabled: true,
markers: {
},
compassEnabled: false,
zoomControlsEnabled: false,
mapType: MapType.normal,
initialCameraPosition: CameraPosition(
target: LatLng(currentLocation.latitude,
currentLocation.longitude),
zoom: 15),
onMapCreated: (controller) {
setState(() {
mapController = controller;
});
},
)
: Center(
child: textCustom(
'Loading...', Colors.black87, 20, 'Hind')),
),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
height: 140.0,
width: MediaQuery.of(context).size.width,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: aktivitasNotifier.listAktivitas.length,
itemBuilder: (BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.only(left: 8.0, top: 8.0),
child: InkWell(
onTap: () {
mapController.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(
aktivitasNotifier
.listAktivitas[index]
.koordinat
.latitude,
aktivitasNotifier
.listAktivitas[index]
.koordinat
.longitude),
zoom: 16.0,
bearing: 19.0,
tilt: 15.0),
),
);
},
child: Stack(
alignment: FractionalOffset(0.5, 0.94),
children: <Widget>[
Material(
elevation: 4.0,
borderRadius: BorderRadius.circular(10.0),
child: Container(
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(10.0),
color: Colors.white,
),
height: 108,
width: 200,
child: Row(
crossAxisAlignment:
CrossAxisAlignment.center,
children: <Widget>[
//
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0),
bottomLeft:
Radius.circular(10.0)),
child: Container(
width: 96,
height: 108,
child: Image.asset(
'assets/trail.png',
fit: BoxFit.cover,
),
),
),
SizedBox(
width: 4,
),
Stack(
alignment:
FractionalOffset(0.5, 0.9),
children: <Widget>[
Container(
width: 100,
child: Padding(
padding:
const EdgeInsets.only(
top: 8.0),
child: Column(
children: <Widget>[
Padding(
padding:
const EdgeInsets
.symmetric(
horizontal:
8.0),
child: Container(
alignment:
Alignment.center,
child: textCustom(
aktivitasNotifier
.listAktivitas[
index]
.nama,
Colors.black87,
14,
'Montserrat'),
),
),
],
),
),
),
ClipRRect(
borderRadius:
BorderRadius.circular(10),
child: InkWell(
onTap: () => Navigator.of(
context)
.push(CupertinoPageRoute(
builder: (BuildContext
context) =>
ProfilAgenWisata(
nama: aktivitasNotifier
.listAktivitas[
index]
.nama,
website: aktivitasNotifier
.listAktivitas[
index]
.website,
noTelepon: aktivitasNotifier
.listAktivitas[
index]
.noTelepon,
email: aktivitasNotifier
.listAktivitas[
index]
.email,
alamat: aktivitasNotifier
.listAktivitas[
index]
.alamat,
deskripsi: aktivitasNotifier
.listAktivitas[
index]
.deskripsi,
))),
child: Container(
alignment: Alignment.center,
color: Color(0xFFDB5C48),
height: 40,
width: 88,
child: textCustom(
'Detail',
Colors.white,
14,
'Montserrat'),
),
),
)
],
),
],
),
),
),
],
)),
);
},
)),
SizedBox(
height: 56.0,
)
],
)
],
));
}
}

The method '[ ]' was called on null

I am running my app and getting the error:
"NoSuchMethodError: The Method '[ ]' was called on null. Receiver: null. Tried calling: ."
This is also happening for "photourl" and "total questions", all three fields that I have in my firestore database.
This error is occurring after I implemented provider, so I am not sure if this is a result of this.
My code is below:
void main() {
runApp(
ChangeNotifierProvider(
builder: (context) => UserModel(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Profile Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Profile'),
);
}
}
class User {
final int name;
final DocumentReference reference;
User.fromMap(Map<String, dynamic> map, {this.reference})
: name = map['name'];
User.fromSnapshot(DocumentSnapshot snapshot)
: this.fromMap(snapshot.data, reference: snapshot.reference);
}
class Photo {
final int photourl;
final DocumentReference reference;
Photo.fromMap(Map<String, dynamic> map, {this.reference})
: photourl = map['photourl'];
Photo.fromSnapshot(DocumentSnapshot snapshot)
: this.fromMap(snapshot.data, reference: snapshot.reference);
}
class Questions {
final int totalquestions;
final DocumentReference reference;
Questions.fromMap(Map<String, dynamic> map, {this.reference})
: totalquestions = map['totalquestions'];
Questions.fromSnapshot(DocumentSnapshot snapshot)
: this.fromMap(snapshot.data, reference: snapshot.reference);
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
final _width = MediaQuery.of(context).size.width;
final _height = MediaQuery.of(context).size.height;
return Consumer<UserModel>(builder: (context, userModel, child) {
return StreamBuilder<DocumentSnapshot>(
stream: Firestore.instance.collection(userModel.uid)
.document(userModel.uid).snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Stack(
children: <Widget>[
new Container(
color: Colors.blue,
),
new Image.network(
snapshot.data['photourl'].toString(),
fit: BoxFit.fill,
),
new BackdropFilter(
filter: new ui.ImageFilter.blur(
sigmaX: 6.0,
sigmaY: 6.0,
),
child: new Container(
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.9),
borderRadius: BorderRadius.all(Radius.circular(50.0)),
),
)),
new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
centerTitle: false,
elevation: 0.0,
backgroundColor: Colors.transparent,
),
drawer: new Drawer(
child: new Container(),
),
backgroundColor: Colors.transparent,
body: new Center(
child: new Column(
children: <Widget>[
new SizedBox(
height: _height / 12,
),
new CircleAvatar(
radius: _width < _height ? _width / 4 : _height / 4,
backgroundImage: NetworkImage(snapshot.data['photourl']),
),
new SizedBox(
height: _height / 25.0,
),
new Text(
snapshot.data['name'],
style: new TextStyle(fontWeight: FontWeight.bold, fontSize: _width / 15, color: Colors.white),
),
new Padding(
padding: new EdgeInsets.only(top: _height / 30, left: _width / 8, right: _width / 8),
),
new Divider(
height: _height / 15,
color: Colors.white,
),
new Row(
children: <Widget>[
rowCell(snapshot.data['totalquestions'], 'Answers'),
rowCell('£ ${int.parse(snapshot.data['totalquestions']) * 2}', 'Earned'),
],
),
new Divider(height: _height / 15, color: Colors.white),
],
),
),
),
],
);
} else {
return CircularProgressIndicator();
}
},
);
});
}
The error simply states that the operator [] is called on a variable that does not contain a Map object and is rather null. I would suggest you to place a check for null or provide a default value for map using ?? everytime before you access a property of map.
This is just speculation but I think you made a mistake when specifying your stream. The collection you query is userModel.uid. Is that how your collection is named?
You should always check if the image is null when you work with NetworkImage since its an async task. The code could look like this:
backgroundImage: snapshot.data['photourl'] != null ?NetworkImage(snapshot.data['photourl']) : Container(),

Trouble pulling data from firestore

database structure screenshotI am building a profile screen and am trying to pull each user's name from a database in firestore using streambuilder. However, my code does not seem to be pulling from the firestore database and I am still getting the same name (each time I run the code) that I had previously hard coded. Below is my code (there are no errors in the actual code). How can I modify my code so that it will actually read from the firestore database?
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:ui' as ui;
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Profile Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Profile'),
);
}
}
class ProfileWidget extends StatelessWidget {
final String userId;
ProfileWidget(this.userId);
#override
Widget build(BuildContext context) {
return StreamBuilder<DocumentSnapshot>(
stream:
Firestore.instance.collection('users').document(userId).snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
debugPrint('the snapshot name is:'+ snapshot.data['name']);
User user = User.fromSnapshot(snapshot.data);
return Row(
children: <Widget>[Text(snapshot.data['name'].toString())]);
} else {
return CircularProgressIndicator();
}
});
}
}
class User {
final int name;
final DocumentReference reference;
User.fromMap(Map<String, dynamic> map, {this.reference}) : name = map['name'];
User.fromSnapshot(DocumentSnapshot snapshot)
: this.fromMap(snapshot.data, reference: snapshot.reference);
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
final _width = MediaQuery.of(context).size.width;
final _height = MediaQuery.of(context).size.height;
final String imgUrl =
'https://pixel.nymag.com/imgs/daily/selectall/2017/12/26/26-eric-schmidt.w700.h700.jpg';
return new Stack(
children: <Widget>[
new Container(
color: Colors.blue,
),
new Image.network(
imgUrl,
fit: BoxFit.fill,
),
new BackdropFilter(
filter: new ui.ImageFilter.blur(
sigmaX: 6.0,
sigmaY: 6.0,
),
child: new Container(
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.9),
borderRadius: BorderRadius.all(Radius.circular(50.0)),
),
)),
new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
centerTitle: false,
elevation: 0.0,
backgroundColor: Colors.transparent,
),
drawer: new Drawer(
child: new Container(),
),
backgroundColor: Colors.transparent,
body: new Center(
child: new Column(
children: <Widget>[
new SizedBox(
height: _height / 12,
),
new CircleAvatar(
radius: _width < _height ? _width / 4 : _height / 4,
backgroundImage: NetworkImage(imgUrl),
),
new SizedBox(
height: _height / 25.0,
),
new Text(
'Eric Schmidt',
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: _width / 15,
color: Colors.white),
),
new Padding(
padding: new EdgeInsets.only(
top: _height / 30, left: _width / 8, right: _width / 8),
child: new Text(
'Snowboarder, Superhero and writer.\nSometime I work at google as Executive Chairman ',
style: new TextStyle(
fontWeight: FontWeight.normal,
fontSize: _width / 25,
color: Colors.white),
textAlign: TextAlign.center,
),
),
new Divider(
height: _height / 30,
color: Colors.white,
),
new Row(
children: <Widget>[
rowCell(343, 'POSTS'),
rowCell(673826, 'FOLLOWERS'),
rowCell(275, 'FOLLOWING'),
],
),
new Divider(height: _height / 30, color: Colors.white),
new Padding(
padding: new EdgeInsets.only(
left: _width / 8, right: _width / 8),
child: new FlatButton(
onPressed: () {},
child: new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Icon(Icons.person),
new SizedBox(
width: _width / 30,
),
new Text('FOLLOW')
],
)),
color: Colors.blue[50],
),
),
],
),
))
],
);
}
Widget rowCell(int count, String type) => new Expanded(
child: new Column(
children: <Widget>[
new Text(
'$count',
style: new TextStyle(color: Colors.white),
),
new Text(type,
style: new TextStyle(
color: Colors.white, fontWeight: FontWeight.normal))
],
));
}

Resources