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

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,
});
}

Related

Error "The method '[]' was called on null. Receiver: null Tried calling: []("0tm2JqPY0oNq5vSM74BqOufhGao1")"

I am getting this error in the poll post Page after added the voting feature to it:
The new method I added is handleTotalVotePosts to handle the count of userPostPolls(in line number 178).
I think the error is getting the userId or something which i am not Sure .
I am not sure what is actually wrong here
The method '[]' was called on null.
Receiver: null
Tried calling: []("0tm2JqPY0oNq5vSM74BqOufhGao1")
But code seems to be correct
This my **pollPost.dart**
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:justpoll/libmodels/user_model.dart';
import 'package:justpoll/screens/chat/chat_data.dart';
import 'package:justpoll/widgets/progress.dart';
import 'package:justpoll/widgets/toast_text.dart';
import '../Constants.dart';
import 'package:justpoll/widgets/custom_image.dart';
import 'package:animated_button/animated_button.dart';
class PollPost extends StatefulWidget {
final String pollPostId;
final String mediaUrl;
final String ownerId;
final String username;
final String caption;
final String category;
final String colorTheme;
final Timestamp duration;
final String question;
final dynamic votesTotal;
final String optText1;
final String optText2;
final String optText3;
final String optText4;
final String optemo1;
final String optemo2;
final String optemo3;
final String optemo4;
final String optCount1;
final String optCount2;
final String optCount3;
final String optCount4;
PollPost({
this.pollPostId,
this.mediaUrl,
this.ownerId,
this.username,
this.caption,
this.category,
this.colorTheme,
this.duration,
this.question,
this.votesTotal,
this.optText1,
this.optText2,
this.optText3,
this.optText4,
this.optemo1,
this.optemo2,
this.optemo3,
this.optemo4,
this.optCount1,
this.optCount2,
this.optCount3,
this.optCount4,
});
factory PollPost.fromDocument(DocumentSnapshot doc) {
return PollPost(
pollPostId: doc['pollPostid'],
mediaUrl: doc['mediaUrl'],
ownerId: doc['ownerId'],
username: doc['username'],
caption: doc['caption'],
category: doc['category'],
colorTheme: doc['colorTheme'],
duration: doc['Duration'],
question: doc['Question'],
votesTotal: doc['votesTotal'],
optText1: doc["options"]["1"]["optionText1"],
optText2: doc["options"]["2"]["optionText2"],
optText3: doc["options"]["3"]["optionText3"],
optText4: doc["options"]["4"]["optionText4"],
optemo1: doc["options"]["1"]["optionEmoji1"],
optemo2: doc["options"]["2"]["optionEmoji2"],
optemo3: doc["options"]["3"]["optionEmoji3"],
optemo4: doc["options"]["4"]["optionEmoji4"],
// optCount1: doc["options"]["1"]["optionCount1"],
// optCount2: doc["options"]["2"]["optionCount2"],
// optCount3: doc["options"]["3"]["optionCount3"],
// optCount4: doc["options"]["4"]["optionCount4"],
);
}
int getreactionsTotalCount(votesTotal) {
if (votesTotal == null) {
return 0;
}
int count = 0;
votesTotal.values.forEach((val) {
if (val = true) {
count += 1;
}
});
return count;
}
#override
_PollPostState createState() => _PollPostState(
pollPostId: this.pollPostId,
mediaUrl: this.mediaUrl,
ownerId: this.ownerId,
username: this.username,
caption: this.caption,
category: this.category,
colorTheme: this.colorTheme,
duration: this.duration,
question: this.question,
optText1: this.optText1,
optText2: this.optText2,
optText3: this.optText3,
optText4: this.optText4,
optemo1: this.optemo1,
optemo2: this.optemo2,
optemo3: this.optemo3,
optemo4: this.optemo4,
votesTotalCount: getreactionsTotalCount(this.votesTotal),
);
}
class _PollPostState extends State<PollPost> {
GlobalKey floatingKey = LabeledGlobalKey("Floating");
bool isFloatingOpen = false;
OverlayEntry floating;
static FirebaseAuth auth = FirebaseAuth.instance;
final userRef = FirebaseFirestore.instance.collection("users");
final pollPostsRef = FirebaseFirestore.instance.collection("pollPosts");
final String currentUserId = auth.currentUser?.uid;
final String pollPostId;
final String mediaUrl;
final String ownerId;
final String username;
final String caption;
final String category;
final String colorTheme;
final Timestamp duration;
final String question;
final String optText1;
final String optText2;
final String optText3;
final String optText4;
final String optemo1;
final String optemo2;
final String optemo3;
final String optemo4;
int votesTotalCount;
Map votesTotal;
bool isVoted;
_PollPostState({
this.pollPostId,
this.mediaUrl,
this.ownerId,
this.username,
this.caption,
this.category,
this.colorTheme,
this.duration,
this.question,
this.votesTotal,
this.votesTotalCount,
this.optText1,
this.optText2,
this.optText3,
this.optText4,
this.optemo1,
this.optemo2,
this.optemo3,
this.optemo4,
});
handleTotalVotePosts() {
bool _isVoted = votesTotal[currentUserId] == true;
if (_isVoted) {
pollPostsRef
.doc(ownerId)
.collection('usersPollPosts')
.doc(pollPostId)
.update({'votesTotal.$currentUserId': false});
setState(() {
votesTotalCount -= 1;
isVoted = false;
votesTotal[currentUserId] = false;
});
} else if (!_isVoted) {
pollPostsRef
.doc(ownerId)
.collection('usersPollPosts')
.doc(pollPostId)
.update({'votesTotal.$currentUserId': true});
setState(() {
votesTotalCount += 1;
isVoted = true;
votesTotal[currentUserId] = true;
});
}
}
OverlayEntry createFloating() {
RenderBox renderBox = floatingKey.currentContext.findRenderObject();
Offset offset = renderBox.localToGlobal(Offset.zero);
return OverlayEntry(builder: (context) {
return Positioned(
left: offset.dx,
top: offset.dy - 70,
child: Material(
color: Colors.transparent,
elevation: 20,
child: ClipRRect(
borderRadius: BorderRadius.circular(40.0),
child: Container(
padding: EdgeInsets.all(5.0),
height: 50,
color: MyColors.black,
child: Row(
children: [
Padding(
padding: const EdgeInsets.all(5.0),
child: AnimatedButton(
onPressed: () {
handleTotalVotePosts();
toastMessage("You voted for $optText1 $optemo1");
setState(() {
if (isFloatingOpen)
floating.remove();
else {
floating = createFloating();
Overlay.of(context).insert(floating);
}
isFloatingOpen = !isFloatingOpen;
});
},
duration: 20,
enabled: true,
width: 30,
height: 30,
color: MyColors.black,
shadowDegree: ShadowDegree.light,
child:
Text(optemo1, style: TextStyle(fontSize: 20.0)))),
Padding(
padding: const EdgeInsets.all(5.0),
child: AnimatedButton(
onPressed: () {
toastMessage("You voted for $optText2 $optemo2");
setState(() {
handleTotalVotePosts();
if (isFloatingOpen)
floating.remove();
else {
floating = createFloating();
Overlay.of(context).insert(floating);
}
isFloatingOpen = !isFloatingOpen;
});
},
duration: 20,
enabled: true,
width: 30,
height: 30,
color: MyColors.black,
shadowDegree: ShadowDegree.light,
child:
Text(optemo2, style: TextStyle(fontSize: 20.0)))),
optText3.isEmpty
? Text("")
: Padding(
padding: const EdgeInsets.all(5.0),
child: AnimatedButton(
onPressed: () {
handleTotalVotePosts();
toastMessage(
"You voted for $optText3 $optemo3");
setState(() {
if (isFloatingOpen)
floating.remove();
else {
floating = createFloating();
Overlay.of(context).insert(floating);
}
isFloatingOpen = !isFloatingOpen;
});
},
duration: 20,
enabled: true,
width: 30,
height: 30,
color: MyColors.black,
shadowDegree: ShadowDegree.light,
child: Text(optemo3,
style: TextStyle(fontSize: 20.0)))),
optText4.isEmpty
? Text("")
: Padding(
padding: const EdgeInsets.all(5.0),
child: AnimatedButton(
onPressed: () {
handleTotalVotePosts();
toastMessage(
"You voted for $optText4 $optemo4");
setState(() {
if (isFloatingOpen)
floating.remove();
else {
floating = createFloating();
Overlay.of(context).insert(floating);
}
isFloatingOpen = !isFloatingOpen;
});
},
duration: 20,
enabled: true,
width: 30,
height: 30,
color: MyColors.black,
shadowDegree: ShadowDegree.light,
child: Text(optemo4,
style: TextStyle(fontSize: 20.0)))),
],
),
),
),
),
);
});
}
buildPollPostHeader() {
return FutureBuilder(
future: userRef.doc(ownerId).get(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return circularProgress();
}
UserModel user = UserModel.fromMap(snapshot.data.data());
return ListTile(
leading: CircleAvatar(
backgroundImage: CachedNetworkImageProvider(user.photoUrl),
backgroundColor: Colors.grey,
),
title: GestureDetector(
onTap: () => toastMessage("showing profile"),
child: Text(
user.username,
style: TextStyle(
color: MyColors.black,
fontWeight: FontWeight.bold,
),
),
),
subtitle: Text(category),
trailing: IconButton(
onPressed: () => toastMessage("pop up menu"),
icon: Icon(Icons.more_vert),
),
);
},
);
}
buildPollPostCenter() {
return Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
question,
style: TextType.boldHeading,
),
),
mediaUrl == null
? Center(
child: Container(
height: 30.0,
))
: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: chachedNetworkImage(
mediaUrl,
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 10.0),
child: Column(
children: [
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
optText1,
style: TextStyle(
color: MyColors.offBlack,
fontSize: 16.0,
),
),
Text(optemo1),
SizedBox(
width: 25.0,
),
Text(
optText2,
style: TextStyle(
color: MyColors.offBlack,
fontSize: 16.0,
),
),
Text(optemo2),
],
),
],
),
SizedBox(height: 13.0),
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
optText3,
style: TextStyle(
color: MyColors.offBlack,
fontSize: 16.0,
),
),
Text(optemo3),
SizedBox(
width: 25.0,
),
Text(
optText4,
style: TextStyle(
color: MyColors.offBlack,
fontSize: 16.0,
),
),
Text(optemo4),
],
),
],
),
],
),
),
],
);
}
buildPollPostFooter() {
return Column(
children: [
Align(
alignment: Alignment.bottomLeft,
child: Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(padding: EdgeInsets.only(top: 40.0, left: 20.0)),
isVoted
? GestureDetector(
key: floatingKey,
onTap: () {
setState(() {
if (isFloatingOpen)
floating.remove();
else {
floating = createFloating();
Overlay.of(context).insert(floating);
}
isFloatingOpen = !isFloatingOpen;
});
},
child: Icon(
Icons.poll,
color: MyColors.offBlack,
size: 28.0,
),
)
: Icon(Icons.check_circle),
Padding(padding: EdgeInsets.only(right: 20.0)),
GestureDetector(
onTap: () => toastMessage("show comments"),
child: Icon(
Icons.chat,
color: MyColors.offBlack,
size: 28.0,
),
),
Padding(padding: EdgeInsets.only(right: 20.0)),
GestureDetector(
onTap: () => toastMessage("saved successfully"),
child: Icon(
Icons.bookmark,
color: MyColors.offBlack,
size: 28.0,
),
),
Padding(padding: EdgeInsets.only(right: 20.0)),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
GestureDetector(
onTap: () => toastMessage("sharing with friends"),
child: Align(
alignment: Alignment.topRight,
child: Icon(
Icons.send,
color: MyColors.offBlack,
size: 28.0,
),
),
),
Padding(padding: EdgeInsets.only(right: 25.0)),
],
),
),
],
),
),
),
Row(
children: [
Container(
margin: EdgeInsets.only(left: 20.0, top: 5.0),
child: Text(
"$votesTotalCount votes",
style: TextStyle(
color: MyColors.black,
fontWeight: FontWeight.bold,
),
),
),
Container(
margin: EdgeInsets.only(left: 20.0, top: 5.0),
child: Text(
"expiring in 4 days",
style: TextStyle(
color: MyColors.black,
fontWeight: FontWeight.bold,
),
),
)
],
),
Padding(
padding: const EdgeInsets.only(top: 5.0, bottom: 10.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: EdgeInsets.only(left: 20.0),
child: Text(
"$username ",
style: TextStyle(
color: MyColors.black,
fontWeight: FontWeight.bold,
),
),
),
Expanded(
child: Text(caption),
),
],
),
)
],
);
}
#override
Widget build(BuildContext context) {
isVoted = (votesTotal[currentUserId] == true);
return Card(
elevation: 1.0,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
buildPollPostHeader(),
buildPollPostCenter(),
buildPollPostFooter(),
],
),
);
}
}
Please help me to get out of this bug.
Thank you :)
Please write the below code inside your handleTotalVotePosts method:
if(votesTotal == null){
return;
}

NoSuchMethodError: 'dart.global.firebase.auth' in the Flutter Chat App

I was creating this Chat App and after implementing the search function I encountered this NoSuchMethodError: tried to call a non-function, such as null: 'dart.global.firebase.auth' problem.
So basically now when I sign up the email and username doesn't get uploaded to firebase auth and Cloud Firestore, which earlier used to happen I think I did some mistake in the search.dart file which seems weird to me.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:intro/helper/constants.dart';
import 'package:intro/services/database.dart';
import 'package:intro/widgets/widgets.dart';
import 'conversation_screen.dart';
class SearchScreen extends StatefulWidget {
#override
_SearchScreenState createState() => _SearchScreenState();
}
class _SearchScreenState extends State<SearchScreen> {
DatabaseMethods databaseMethods = new DatabaseMethods();
TextEditingController searchTextEditingController =
new TextEditingController();
QuerySnapshot searchSnapshot;
Widget searchList() {
return searchSnapshot != null
? ListView.builder(
itemCount: searchSnapshot.docs.length,
shrinkWrap: true,
itemBuilder: (context, index) {
return searchTile(
searchSnapshot.docs[index].data()["name"],
searchSnapshot.docs[index].data()["email"],
);
})
: Container();
}
initiateSearch() {
databaseMethods
.getUserByUsername(searchTextEditingController.text)
.then((val) {
setState(() {
searchSnapshot = val;
});
});
}
createChatroomAndStartConversation({String userName}) {
String chatRoomId = getChatRoomId(userName, Constants.myName);
List<String> users = [userName, Constants.myName];
Map<String, dynamic> chatRoomMap = {
"users": users,
"chatroomid": chatRoomId
};
DatabaseMethods().createChatRoom(chatRoomId, chatRoomMap);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ConversationScreen(),
));
}
Widget searchTile(String userName, String userEmail) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(userName, style: mediumTextStyle()),
Text(userEmail, style: mediumTextStyle())
],
),
Spacer(),
GestureDetector(
onTap: () {
createChatroomAndStartConversation(userName: userName);
},
child: Container(
decoration: BoxDecoration(
color: Colors.blue, borderRadius: BorderRadius.circular(30)),
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 6),
child: Text(
"Message",
style: mediumTextStyle(),
),
),
)
],
),
);
}
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: appBarMain(context),
body: Container(
child: Column(
children: [
Container(
color: Color(0x54FFFFFF),
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Row(children: [
Expanded(
child: TextField(
controller: searchTextEditingController,
style: TextStyle(
color: Colors.white,
),
decoration: InputDecoration(
hintText: "Search Username",
hintStyle: TextStyle(
color: Colors.white54,
),
border: InputBorder.none),
),
),
GestureDetector(
onTap: () {
initiateSearch();
},
child: Container(
height: 35,
width: 35,
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
const Color(0x36FFFFFF),
const Color(0x0FFFFFFF)
]),
borderRadius: BorderRadius.circular(30)),
padding: EdgeInsets.all(1),
child: Icon(
Icons.search,
color: Colors.white,
)),
)
]),
),
searchList()
],
),
),
);
}
}
getChatRoomId(String a, String b) {
if (a.substring(0, 1).codeUnitAt(0) > b.substring(0, 1).codeUnitAt(0)) {
return "$b\_$a";
} else {
return "$a\_$b";
}
}
and just in case there is an error with the signUp.dart file here it is.
import 'package:flutter/material.dart';
import 'package:intro/helper/helperfunctions.dart';
import 'package:intro/services/auth.dart';
import 'package:intro/services/database.dart';
import 'package:intro/widgets/widgets.dart';
import 'chatRoomsScreen.dart';
class SignUp extends StatefulWidget {
final Function toggle;
SignUp(this.toggle);
#override
_SignUpState createState() => _SignUpState();
}
class _SignUpState extends State<SignUp> {
bool isLoading = false;
AuthMethods authMethods = new AuthMethods();
DatabaseMethods databaseMethods = new DatabaseMethods();
final formKey = GlobalKey<FormState>();
TextEditingController userNameTextEditingController =
new TextEditingController();
TextEditingController emailTextEditingController =
new TextEditingController();
TextEditingController passwordTextEditingController =
new TextEditingController();
signMeUP() {
if (formKey.currentState.validate()) {
Map<String, String> userInfoMap = {
"name": userNameTextEditingController.text,
"email": emailTextEditingController.text,
};
HelperFunctions.saveUserEmailSharedPreference(
emailTextEditingController.text);
HelperFunctions.saveUserNameSharedPreference(
userNameTextEditingController.text);
setState(() {
isLoading = true;
});
authMethods
.signUpwithemailandpassword(emailTextEditingController.text,
passwordTextEditingController.text)
.then((value) {
// print("$value.uid");
databaseMethods.uploadUserInfo(userInfoMap);
HelperFunctions.saveUserLoggedInSharedPreference(true);
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => ChatRoom()));
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: appBarMain(context),
body: isLoading
? Container(
child: Center(child: CircularProgressIndicator()),
)
: SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height - 60,
alignment: Alignment.bottomCenter,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 24),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Form(
key: formKey,
child: Column(
children: [
TextFormField(
validator: (val) {
return val.isEmpty || val.length < 2
? "Invalid Username (Needs to be more than 2 characters)"
: null;
},
controller: userNameTextEditingController,
style: simpleTextStyle(),
decoration: textfieldInputDecoration("username"),
),
TextFormField(
validator: (val) {
return RegExp(
r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+")
.hasMatch(val)
? null
: "Enter correct email";
},
controller: emailTextEditingController,
style: simpleTextStyle(),
decoration: textfieldInputDecoration("email"),
),
TextFormField(
obscureText: true,
validator: (val) {
return val.length < 6
? "Please provide with 6+ character"
: null;
},
controller: passwordTextEditingController,
style: simpleTextStyle(),
decoration: textfieldInputDecoration("password"),
),
],
),
),
SizedBox(
height: 10,
),
Container(
alignment: Alignment.centerRight,
child: Container(
padding:
EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Text(
"Forgot Password?",
style: simpleTextStyle(),
),
),
),
SizedBox(
height: 10,
),
GestureDetector(
onTap: () {
signMeUP();
},
child: Container(
alignment: Alignment.center,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.symmetric(vertical: 20),
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
const Color(0xff007EF4),
const Color(0xff2A75BC)
]),
borderRadius: BorderRadius.circular(30)),
child: Text("Sign Up", style: mediumTextStyle()),
),
),
SizedBox(
height: 10,
),
Container(
alignment: Alignment.center,
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.symmetric(vertical: 20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(30)),
child: Text("Sign Up with Google",
style:
TextStyle(color: Colors.black, fontSize: 18)),
),
SizedBox(
height: 15,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Already have an account? ",
style: mediumTextStyle(),
),
GestureDetector(
onTap: () {
widget.toggle();
},
child: Container(
padding: EdgeInsets.symmetric(vertical: 8),
child: Text(
"Sign in now",
style: TextStyle(
color: Colors.white,
fontSize: 17,
decoration: TextDecoration.underline),
),
),
),
],
),
SizedBox(
height: 50,
)
],
),
),
),
),
);
}
}
And if there is any file anyone of you want: GitHub: Chat App
Because you Haven't initialize the method

How to perform CRUD operations with BLoC pattern?

I was learning on flutter how to perform CRUD operations using BLoC pattern, I saw a tutorial online and try to apply it. C,R,U are OK, but deletion is not working. this is the source code.
Please Help !
file todo_bloc.dart
import 'package:zencartos/models/todo.dart';
import 'package:zencartos/repository/todo_repository.dart';
class TodoBloc {
//Get instance of the Repository
final _todoRepository = TodoRepository();
final _todoController = StreamController<List<Todo>>.broadcast();
get todos => _todoController.stream;
TodoBloc() {
getTodos();
}
getTodos({String query}) async {
_todoController.sink.add(await _todoRepository.getAllTodos(query: query));
}
addTodo(Todo todo) async {
await _todoRepository.insertTodo(todo);
getTodos();
}
updateTodo(Todo todo) async {
await _todoRepository.updateTodo(todo);
getTodos();
}
deleteTodoById(int id) async {
_todoRepository.deleteTodoById(id);
getTodos();
}
dispose() {
_todoController.close();
}
}
DAO Page todo_dao.dart
import 'package:zencartos/database/database.dart';
import 'package:zencartos/models/todo.dart';
class TodoDao {
final dbProvider = DatabaseProvider.dbProvider;
Future<int> createTodo(Todo todo) async{
final db = await dbProvider.database;
var result = db.insert(todoTABLE, todo.toDatabaseJson());
return result;
}
Future<List<Todo>> getTodos({List<String> columns, String query})
async{
final db = await dbProvider.database;
List<Map<String, dynamic>> result;
if (query != null){
if (query.isNotEmpty)
result = await db.query(todoTABLE, columns: columns, where: 'description LIKE ?', whereArgs: ["%$query%"]);
} else {
result = await db.query(todoTABLE, columns: columns);
}
List<Todo> todos = result.isNotEmpty
? result.map((item)=> Todo.fromDatabaseJson(item)).toList()
: [];
return todos;
}
//Update Todo record
Future<int> updateTodo(Todo todo) async{
final db = await dbProvider.database;
var result = await db.update(todoTABLE, todo.toDatabaseJson(),
where: "id = ?", whereArgs: [todo.id]);
return result;
}
//Delete Todo records
Future<int> deleteTodo(int id) async{
final db = await dbProvider.database;
var result = await db.delete(todoTABLE, where: 'id = ?', whereArgs: [id]);
return result;
}
}
Database Page database.dart
import 'dart:io';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
final todoTABLE = 'Todo';
class DatabaseProvider {
static final DatabaseProvider dbProvider = DatabaseProvider();
Database _database;
Future<Database> get database async {
if (_database != null) return _database;
_database = await createDatabase();
return _database;
}
createDatabase() async {
Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, "ReactiveTodo");
var database = await openDatabase(path, version: 1, onCreate: initDB, onUpgrade: onUpgrade);
return database;
}
void onUpgrade(Database database, int oldVersion, int newVersion){
if (newVersion > oldVersion){}
}
void initDB(Database database, int version) async{
await database.execute("CREATE TABLE $todoTABLE ("
"id INTEGER PRIMARY KEY, "
"description TEXT, "
"is_done INTEGER "
")");
}
}
Model page todo.dart
class Todo{
int id;
String description;
bool isDone = false;
Todo({this.id, this.description, this.isDone = false});
factory Todo.fromDatabaseJson(Map<String, dynamic> data) => Todo(
id: data['data'],
description: data['description'],
isDone: data['is_done'] == 0 ? false : true,
);
Map<String, dynamic> toDatabaseJson() => {
"id": this.id,
"description": this.description,
"is_done": this.isDone == false ? 0 : 1,
};
}
View page home_Page2.dart
import 'package:flutter/services.dart';
import 'package:zencartos/bloc/todo_bloc.dart';
import 'package:zencartos/models/todo.dart';
class HomePage2 extends StatelessWidget {
HomePage2({Key key, this.title}) : super(key: key);
final TodoBloc todoBloc = TodoBloc();
final String title;
//Allows Todo card to be dismissable horizontally
final DismissDirection _dismissDirection = DismissDirection.horizontal;
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark.copyWith(
statusBarColor: Colors.white,
systemNavigationBarColor: Colors.white,
systemNavigationBarIconBrightness: Brightness.dark,
statusBarBrightness: Brightness.dark));
return Scaffold(
resizeToAvoidBottomPadding: false,
body: SafeArea(
child: Container(
color: Colors.white,
padding:
const EdgeInsets.only(left: 2.0, right: 2.0, bottom: 2.0),
child: Container(
//This is where the magic starts
child: getTodosWidget()))),
bottomNavigationBar: BottomAppBar(
color: Colors.white,
child: Container(
decoration: BoxDecoration(
border: Border(
top: BorderSide(color: Colors.grey, width: 0.3),
)),
child: Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
IconButton(
icon: Icon(
Icons.menu,
color: Colors.indigoAccent,
size: 28,
),
onPressed: () {
//just re-pull UI for testing purposes
todoBloc.getTodos();
}),
Expanded(
child: Text(
"Todo",
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w600,
fontFamily: 'RobotoMono',
fontStyle: FontStyle.normal,
fontSize: 19),
),
),
Wrap(children: <Widget>[
IconButton(
icon: Icon(
Icons.search,
size: 28,
color: Colors.indigoAccent,
),
onPressed: () {
_showTodoSearchSheet(context);
},
),
Padding(
padding: EdgeInsets.only(right: 5),
)
])
],
),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: Padding(
padding: EdgeInsets.only(bottom: 25),
child: FloatingActionButton(
elevation: 5.0,
onPressed: () {
_showAddTodoSheet(context);
},
backgroundColor: Colors.white,
child: Icon(
Icons.add,
size: 32,
color: Colors.indigoAccent,
),
),
));
}
void _showAddTodoSheet(BuildContext context) {
final _todoDescriptionFormController = TextEditingController();
showModalBottomSheet(
context: context,
builder: (builder) {
return new Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: new Container(
color: Colors.transparent,
child: new Container(
height: 230,
decoration: new BoxDecoration(
color: Colors.white,
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(10.0),
topRight: const Radius.circular(10.0))),
child: Padding(
padding: EdgeInsets.only(
left: 15, top: 25.0, right: 15, bottom: 30),
child: ListView(
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextFormField(
controller: _todoDescriptionFormController,
textInputAction: TextInputAction.newline,
maxLines: 4,
style: TextStyle(
fontSize: 21, fontWeight: FontWeight.w400),
autofocus: true,
decoration: const InputDecoration(
hintText: 'I have to...',
labelText: 'New Todo',
labelStyle: TextStyle(
color: Colors.indigoAccent,
fontWeight: FontWeight.w500)),
validator: (String value) {
if (value.isEmpty) {
return 'Empty description!';
}
return value.contains('')
? 'Do not use the # char.'
: null;
},
),
),
Padding(
padding: EdgeInsets.only(left: 5, top: 15),
child: CircleAvatar(
backgroundColor: Colors.indigoAccent,
radius: 18,
child: IconButton(
icon: Icon(
Icons.save,
size: 22,
color: Colors.white,
),
onPressed: () {
final newTodo = Todo(
description:
_todoDescriptionFormController
.value.text);
if (newTodo.description.isNotEmpty) {
/*Create new Todo object and make sure
the Todo description is not empty,
because what's the point of saving empty
Todo
*/
todoBloc.addTodo(newTodo);
//dismisses the bottomsheet
Navigator.pop(context);
}
},
),
),
)
],
),
],
),
),
),
),
);
});
}
void _showTodoSearchSheet(BuildContext context) {
final _todoSearchDescriptionFormController = TextEditingController();
showModalBottomSheet(
context: context,
builder: (builder) {
return new Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: new Container(
color: Colors.transparent,
child: new Container(
height: 230,
decoration: new BoxDecoration(
color: Colors.white,
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(10.0),
topRight: const Radius.circular(10.0))),
child: Padding(
padding: EdgeInsets.only(
left: 15, top: 25.0, right: 15, bottom: 30),
child: ListView(
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextFormField(
controller: _todoSearchDescriptionFormController,
textInputAction: TextInputAction.newline,
maxLines: 4,
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.w400),
autofocus: true,
decoration: const InputDecoration(
hintText: 'Search for todo...',
labelText: 'Search *',
labelStyle: TextStyle(
color: Colors.indigoAccent,
fontWeight: FontWeight.w500),
),
validator: (String value) {
return value.contains('#')
? 'Do not use the # char.'
: null;
},
),
),
Padding(
padding: EdgeInsets.only(left: 5, top: 15),
child: CircleAvatar(
backgroundColor: Colors.indigoAccent,
radius: 18,
child: IconButton(
icon: Icon(
Icons.search,
size: 22,
color: Colors.white,
),
onPressed: () {
/*This will get all todos
that contains similar string
in the textform
*/
todoBloc.getTodos(
query:
_todoSearchDescriptionFormController
.value.text);
//dismisses the bottomsheet
Navigator.pop(context);
},
),
),
)
],
),
],
),
),
),
),
);
});
}
Widget getTodosWidget() {
return StreamBuilder(
stream: todoBloc.todos,
builder: (BuildContext context, AsyncSnapshot<List<Todo>> snapshot) {
return getTodoCardWidget(snapshot);
},
);
}
Widget getTodoCardWidget(AsyncSnapshot<List<Todo>> snapshot) {
if (snapshot.hasData) {
return snapshot.data.length != 0
? ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, itemPosition) {
Todo todo = snapshot.data[itemPosition];
final Widget dismissibleCard = new Dismissible(
background: Container(
child: Padding(
padding: EdgeInsets.only(left: 10),
child: Align(
alignment: Alignment.centerLeft,
child: Text(
"Deleting",
style: TextStyle(color: Colors.white),
),
),
),
color: Colors.redAccent,
),
onDismissed: (direction) {
todoBloc.deleteTodoById(todo.id);
},
direction: _dismissDirection,
key: new ObjectKey(todo),
child: Card(
shape: RoundedRectangleBorder(
side: BorderSide(color: Colors.grey[200], width: 0.5),
borderRadius: BorderRadius.circular(5),
),
color: Colors.white,
child: ListTile(
leading: InkWell(
onTap: () {
//Reverse the value
todo.isDone = !todo.isDone;
todoBloc.updateTodo(todo);
},
child: Container(
//decoration: BoxDecoration(),
child: Padding(
padding: const EdgeInsets.all(15.0),
child: todo.isDone
? Icon(
Icons.done,
size: 26.0,
color: Colors.indigoAccent,
)
: Icon(
Icons.check_box_outline_blank,
size: 26.0,
color: Colors.tealAccent,
),
),
),
),
title: Text(
todo.description,
style: TextStyle(
fontSize: 16.5,
fontFamily: 'RobotoMono',
fontWeight: FontWeight.w500,
decoration: todo.isDone
? TextDecoration.lineThrough
: TextDecoration.none),
),
)),
);
return dismissibleCard;
},
)
: Container(
child: Center(
//this is used whenever there 0 Todo
//in the data base
child: noTodoMessageWidget(),
));
} else {
return Center(
child: loadingData(),
);
}
}
Widget loadingData() {
todoBloc.getTodos();
return Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircularProgressIndicator(),
Text("Loading...",
style: TextStyle(fontSize: 19, fontWeight: FontWeight.w500))
],
),
),
);
}
Widget noTodoMessageWidget() {
return Container(
child: Text(
"Start adding Todo...",
style: TextStyle(fontSize: 19, fontWeight: FontWeight.w500),
),
);
}
dispose() {
todoBloc.dispose();
}
}
repository page todo_repository.dart
import 'package:zencartos/models/todo.dart';
class TodoRepository {
final todoDao = TodoDao();
Future getAllTodos({String query}) => todoDao.getTodos(query: query);
Future insertTodo(Todo todo) => todoDao.createTodo(todo);
Future updateTodo(Todo todo) => todoDao.updateTodo(todo);
Future deleteTodoById(int id) => todoDao.deleteTodo(id);
//We are not going to use this in the demo
//Future deleteAllTodos() => todoDao.deleteAllTodos();
}
In your todo_bloc.dart, your delete method should be:
deleteTodoById(int id) async {
await _todoRepository.deleteTodoById(id);
getTodos();
}

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))
],
));
}

How to get array data back to mobile screen from firebase (Flutter)

How to get back array data to the mobile screen.
The String in the firebase is retrieved easily but I have problem with array data.
1) main.dart :
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'firestoreservice.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'taskscreen.dart';
import 'task.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter ToDo APP',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Color(0xff543B7A),
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<Task> items;
FirestoreService fireServ = new FirestoreService();
StreamSubscription<QuerySnapshot> todoTasks;
#override
void initState() {
super.initState();
items=new List();
todoTasks?.cancel();
todoTasks=fireServ.getTaskList().listen((QuerySnapshot snapshot){
final List<Task> tasks=snapshot.documents
.map((documentSnapshot) => Task. fromMap(documentSnapshot.data))
.toList();
setState(() {
this.items = tasks;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Column(
children: <Widget>[
_myAppBar(context),
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height - 80,
child: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return Stack(children: <Widget>[
// The containers in the background
Column(children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 8.0, right: 8.0),
child: Container(
width: MediaQuery.of(context).size.width,
height: 80.0,
child: Padding(
padding: EdgeInsets.only(top: 8.0, bottom: 8.0),
child: Material(
color: Colors.white,
elevation: 14.0,
shadowColor: Color(0x802196F3),
child: Center(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'${items[index].name}',
style: TextStyle(
color: Colors.black,
fontSize: 20.0),
),
Text(
'${items[index].size}',
style: TextStyle(
color: Colors.black,
fontSize: 20.0),
),
Container(
child: Image.network(
'${items[index].imageU}',
)),
],
),
),
),
),
),
),
),
]),
]);
}),
),
],
),
);
}
Widget todoType(String icontype) {
IconData iconval;
Color colorval;
switch (icontype) {
case 'travel':
iconval = FontAwesomeIcons.mapMarkerAlt;
colorval = Color(0xff4158ba);
break;
case 'shopping':
iconval = FontAwesomeIcons.shoppingCart;
colorval = Color(0xfffb537f);
break;
case 'gym':
iconval = FontAwesomeIcons.dumbbell;
colorval = Color(0xff4caf50);
break;
case 'party':
iconval = FontAwesomeIcons.glassCheers;
colorval = Color(0xff9962d0);
break;
default:
iconval = FontAwesomeIcons.tasks;
colorval = Color(0xff0dc8f5);
//
}
return CircleAvatar(
backgroundColor: colorval,
child: Icon(iconval, color: Colors.white, size: 20.0),
);
}
Widget _myAppBar(context) {
return Container(
height: 80.0,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
const Color(0xFFFA7397),
const Color(0xFFFDDE42),
],
begin: const FractionalOffset(0.0, 0.0),
end: const FractionalOffset(1.0, 0.0),
stops: [0.0, 1.0],
tileMode: TileMode.clamp),
),
child: Padding(
padding: const EdgeInsets.only(top: 16.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
flex: 5,
child: Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'ToDo Tasks',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 20.0),
),
),
),
),
Expanded(
flex: 1,
child: Container(
child: IconButton(
icon: Icon(
FontAwesomeIcons.search,
color: Colors.white,
),
onPressed: () {
//
}),
),
),
],
)),
),
);
}
}
2) task.dart
class Task{
String _name;
String _size;
Task(this._name ,this._size);
Task.map(dynamic obj){
this._name = obj['name'];
this._size=obj['size'];
List<String> imageU= new List<String>();
}
String get name=> _name;
String get size=>_size;
Task.fromMap(Map<String,dynamic> map){
this._name = map['name'];
this._size= map['size'];
this.imageU= List.from(map['images']);
}
}
3) firestoreservice.dart
import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'task.dart';
final CollectionReference myCollection =
Firestore.instance.collection('products');
class FirestoreService {
Future<Task> createTODOTask(String name, String size) async {
final TransactionHandler createTransaction = (Transaction tx) async {
final DocumentSnapshot ds = await tx.get(myCollection.document());
};
return Firestore.instance.runTransaction(createTransaction).then((mapData) {
return Task.fromMap(mapData);
}).catchError((error) {
print('error: $error');
return null;
});
}
Stream<QuerySnapshot> getTaskList({int offset, int limit}) {
Stream<QuerySnapshot> snapshots = myCollection.snapshots();
if (offset != null) {
snapshots = snapshots.skip(offset);
}
if (limit != null) {
snapshots = snapshots.take(limit);
}
return snapshots;
}
}
How to get back array data to the mobile screen. The String in the firebase is retrieved easily but I have a problem with array data.
Convert task.dart to see what solution will work:
class Task{
String name;
List<String> size= new List<String>();
Task.fromMap(Map<String,dynamic> map){
this.name = map['name'];
this.size= List.from(map['size' ]);
}
}
And make sure all the documents in the image have "size" field.

Resources