How do I retrive firebase data in flutter - firebase

I am trying to get a list of data from a firebase database and display it as a list in my flutter app, at the moment I cannot get the data to appear, on the UI.When I try and print the list it does not contain any values when it should show the names I have entered in the database.
This is the database that I am trying to retrieve:
This is the code that I have implemented for my UI, any ideas on what is the issue here?
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_database/ui/firebase_animated_list.dart';
import 'SignInSuccessPage.dart';
class SignInPage extends StatefulWidget {
#override
SignInPageState createState() => SignInPageState();
}
class SignInPageState extends State<SignInPage> {
List<Volunteer> volunteers;
Volunteer volunteer;
DatabaseReference volunteerRef;
#override
void initState() {
super.initState();
volunteers = new List();
volunteer = Volunteer("","", "");
final FirebaseDatabase database = FirebaseDatabase.instance; /
volunteerRef = database.reference().child('volunteerapp-cec4f');
volunteerRef.onChildAdded.listen(_onEntryAdded);
volunteerRef.onChildChanged.listen(_onEntryChanged);
}
_onEntryAdded(Event event) {
setState(() {
volunteers.add(Volunteer.fromSnapshot(event.snapshot));
});
}
_onEntryChanged(Event event) {
var old = volunteers.singleWhere((entry) {
return entry.key == event.snapshot.key;
});
setState(() {
volunteers[volunteers.indexOf(old)] = Volunteer.fromSnapshot(event.snapshot);
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('List of Names'),
),
resizeToAvoidBottomPadding: false,
body: Column(
children: <Widget>[
Flexible(
child: FirebaseAnimatedList(
query: volunteerRef,
itemBuilder: (BuildContext context, DataSnapshot snapshot,
Animation<double> animation, int index) {
return new ListTile(
title: Text(volunteers[index].firstName),
subtitle: Text(volunteers[index].lastName),
);
},
),
),
],
),
);
}
}
//the volunteer class which contains all the info about each volunteer object and links to firebase
class Volunteer {
String key;
String firstName;
String lastName;
Volunteer(this.key, this.firstName, this.lastName);
Volunteer.fromSnapshot(DataSnapshot snapshot)
: key = snapshot.key,
firstName = snapshot.value["firstName"],
lastName = snapshot.value["lastName"];
toJson() {
return {
"key": key,
"firstName": firstName,
"lastName": lastName,
};
}
}

You don't need to include the name of your project as a child call, it's already in the base reference.
So:
volunteerRef = database.reference();

Related

Parameter is null instead of an id with ModalRoute.of()

I am developing a mobile App with Flutter and Firebase.
I am trying to use pushNamed() and hand over a parameter. (an id)
I don't know how i could solve my problem.
Here is my Code:
#override
void didChangeDependencies() {
if (_isInit) {
print(ModalRoute.of(context).settings.arguments);
final productId = ModalRoute.of(context).settings.arguments;
if (productId != null) {
_editedAngebot = Provider.of<Angebote>(context).findByID(productId);
_initValues = {
'titel': _editedAngebot.titel,
'beschreibung': _editedAngebot.beschreibung,
'semester': _editedAngebot.semester.toString(),
'fach': _editedAngebot.fach,
'abteilung': _editedAngebot.abteilung,
};
}
}
_isInit = false;
super.didChangeDependencies();
}
And the other class, where I set the parameter. My "Angebot" object only has a default constructor.
trailing: isAllowed()
? IconButton(
icon: Icon(Icons.edit),
onPressed: () {
Navigator.of(context).maybePop();
Navigator.of(context)
.pushNamed('/editAngebot', arguments: id);
})
Why is my ID null?
Your Id is null because you are popping a page first then pushing new page .
Use pushReplacementNamed()
Here is a code sample
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: FirstPage(),
routes:{
Secondpage.routeName:(context)=>Secondpage(),
}
);
}
}
class FirstPage extends StatelessWidget {
final String id = '01';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child:ElevatedButton(
child: Text('GoTo secondPage'),
onPressed: (){
Navigator.of(context).pushReplacementNamed(Secondpage.routeName,arguments: id);
},
))
);
}
}
class Secondpage extends StatelessWidget {
static const routeName = 'secondpage';
#override
Widget build(BuildContext context) {
final data = ModalRoute.of(context).settings.arguments as String;
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(child:Text('$data')),
ElevatedButton(
child: Text('GoTo FirstPage'),
onPressed: (){
Navigator.of(context).pop();
},
)
],
)
);
}
}
you should probably change the id defined in the class to a dynamic type and it would work.. tested this and it works as fine
class Product with ChangeNotifier {
//changed to dynamic as errors with null and string came topping up
final dynamic id;
final String title;
final String description;
Product(
{required this.id,
required this.title,
required this.description,
});

Exception: Bad state: cannot get a field on a DocumentSnapshotPlatform which does not exist

The method mentioned in this thread https://stackoverflow.com/a/50867881/13153574 I am trying to fetch data from Firestore. But getting the following exception. The 'name' field is a String and 'overview' field is a List of Strings.
Bad state: cannot get a field on a DocumentSnapshotPlatform which does not exist
My code is as below:
import 'package:firebaseAuth/firebaseAuthDemo.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class FindDiseases extends StatefulWidget {
final User user;
const FindDiseases({Key key, this.user}) : super(key: key);
#override
_FindDiseasesState createState() => _FindDiseasesState();
}
class _FindDiseasesState extends State<FindDiseases> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
FirebaseAuth _auth = FirebaseAuth.instance;
List diseasesList = [];
//dynamic data;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.teal,
automaticallyImplyLeading: false,
title: Text(
"Diseases List",
),
),
key: _scaffoldKey,
body: Center(
child: FlatButton(
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text("get Disease Record"),
StreamBuilder<DiseaseRecord>(
stream: getDisease(),
builder: (BuildContext c, AsyncSnapshot<DiseaseRecord> data) {
if (data?.data == null) return Text("Error");
DiseaseRecord r = data.data;
return Text("${r.name}");
},
),
],
),
onPressed: () {
getDisease();
},
),
),
);
}
Future _signOut() async {
await _auth.signOut();
}
}
Stream<DiseaseRecord> getDisease() {
return FirebaseFirestore.instance.collection("diseases").doc().get().then(
(snapshot) {
try {
return DiseaseRecord.fromSnapshot(snapshot);
} catch (e) {
print(">>> Error:"+e.toString());
return null;
}
},
).asStream();
}
class DiseaseRecord {
String name;
List<String> overview = new List<String>();
DiseaseRecord.fromSnapshot(DocumentSnapshot snapshot)
: name = snapshot['name'],
overview = List.from(snapshot['overview']);
}
Data is something like as below:
name: "name--"
overview: "['a', 'b', 'c']"
The problem is here:
return FirebaseFirestore.instance.collection("diseases").doc().get()
Calling doc() without any arguments creates a reference to a new, non-existing document. Then calling get() on that, returns a DocumentSnapshot for a non-existing document, and trying to get fields from that is an invalid operation.
Most likely you'll need to know the ID of the disease document you're trying to load, and pass that in to the call to doc(id).

Undefined class 'AllCoursesSnapshot'

I am trying to retrieve data from firebase database and display it on my UI. This is the code written :
class AllCourses {
String courseName;
String teacher;
String category;
AllCourses(this.courseName, this.teacher, this.category);
}
import 'package:creators_club/firestore/courses.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
class BusinessPage extends StatefulWidget {
#override
_BusinessPageState createState() => _BusinessPageState();
}
class _BusinessPageState extends State<BusinessPage> {
List<AllCourses> coursesList = [];
#override
void initState(){
super.initState();
DatabaseReference referenceAllCourses = FirebaseDatabase.instance.reference().child('AllCourses');
referenceAllCourses.once().then(((AllCoursesSnapshot allCoursesSnapshot){
coursesList.clear();
var keys = allCoursesSnapshot.value.keys;
var values = allCoursesSnapshot.value;
for(var key in keys){
AllCourses allCourses = new AllCourses(
values [key]["courseName"],
values [key]["teacher"],
values [key]["category"],
);
coursesList.add(allCourses);
}
setState(() {
//HERE
});
}));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),),
title: Text("Creator's Club"),
backgroundColor: Color(0xff2657ce),
elevation: 0,),
body: coursesList.length == 0 ? Center(child: Text("No Data Avail", style: TextStyle(fontSize: 15),)): ListView.builder(
itemCount: coursesList.length,
itemBuilder: (_,index){
return CardUI(coursesList[index].courseName, coursesList[index].teacher, coursesList[index].category);}
)
);
}
}
}
Why isn't the AllCoursesSnapshot being recognized? It says that it is "Type: Null Function(dynamic)".
Here is a picture of the database table in Realtime Database: (https://imgur.com/a/xDZy1SW).
It is not recognized because there is no class called AllCoursesSnapshot. The once() method belongs to the firebase_database plugin, and it returns a Future<DataSnapshot>, therefore you have to do the following:
referenceAllCourses.once().then((DataSnapshot dataSnapshot){
Also replace allCoursesSnapshot with dataSnapshot in the other parts of your code.

Why is the data I pulled from firebase coming from null?

Patients model dart file;
import 'package:flutter/material.dart';
class Patients {
String patientId;
String nurseId;
String username;
DateTime date;
int age;
List<String> diseases;
//final fotograf olacak
Patients({#required this.patientId,this.nurseId,this.date,this.username,this.age,this.diseases});
factory Patients.fromJson(Map<String, dynamic> json){
return Patients(
patientId: json["patientId"],
nurseId: json["nurseId"],
username: json["username"],
date: json["date"],
age: json["age"],
diseases: json["diseases"],
);
}
Map<String,dynamic> toMap(){
return {
"patientId": patientId,
"nurseId" : nurseId,
"username" : username,
"date" : date,
"age" : age,
"diseases" : diseases,
};
}
}
PatientsProvider dart file;
import 'package:flutter/material.dart';
import 'package:imlearningfirebase/model/patients.dart';
import 'package:uuid/uuid.dart';
import 'package:imlearningfirebase/services/fireStoreService.dart';
class PatientsProvider with ChangeNotifier{
final fireStoreService = FireStoreService();
String _patientId;
String _nurseId;
DateTime _date;
String _username;
int _age;
List<String> _diseases;
var uuid = Uuid();
///Getters
String get username =>_username;
int get age => _age;
List<String> get diseases => _diseases;
DateTime get date => _date;
Stream<List<Patients>> get getPatients => fireStoreService.getEntries();
savePatient(int agee,String usernamee,List<String> diseasess){
if(_nurseId == null){
///add
var newPatient = Patients(patientId: uuid.v1(),nurseId:fireStoreService.getCurrentUserId().toString(),date:DateTime.now(),username: usernamee,age: agee,diseases: diseasess);
print(newPatient.username);
fireStoreService.setPatients(newPatient);
}else{
var updatedPatients = Patients(patientId: uuid.v1(),nurseId:fireStoreService.getCurrentUserId().toString(),date:DateTime.now(),username: usernamee,age: agee,diseases: diseasess);
fireStoreService.setPatients(updatedPatients);
}
}
}
FireStoreService dart file;
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
/// Local Importlar
import '../model/patients.dart';
class FireStoreService{
FirebaseFirestore _db = FirebaseFirestore.instance;
final FirebaseAuth auth = FirebaseAuth.instance;
///Get Entries
Stream<List<Patients>> getEntries(){
return _db
.collection("patients")
.snapshots()
.map((snapshot) => snapshot.docs
.map((doc) => Patients.fromJson(doc.data()))
.toList());
}}
Home screen;
import 'package:flutter/material.dart';
import 'package:imlearningfirebase/provider/patienstProvider.dart';
import 'package:provider/provider.dart';
class HomePage extends StatelessWidget{
#override
Widget build(BuildContext context) {
final patientsProvider = Provider.of<PatientsProvider>(context);
return Scaffold(
appBar: AppBar(
title: Text("Patients"),
),
floatingActionButton: Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 50.0),
child: FloatingActionButton(
onPressed: () async {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => AddPatient()),
);
},
child: Icon(
Icons.add,
color: Colors.blueAccent,
),
backgroundColor: Colors.green,
),
),
body:StreamBuilder<List<Patients>>(
stream: patientsProvider.getPatients,
builder: (context,snapshot){
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context,index){
return ListTile(
trailing:
Icon(Icons.edit, color: Theme.of(context).accentColor),
title: Text('${DateTime.now()}'
),
);
}
);
}
)
);
}
}
I am trying to create a system where a person has to register and register another person. I created a model so that the registered person creates the profile of the other person. The name of this model is patients. I use the provider package to access patients functions. I have created a function named take patients in Firestore and put it in the patient provider. Finally, I call this on the Home page. but the length came null. I can not see the error I would be glad if you help.
I didn't use your FireStoreService() class. This might be a bit messy but it worked for me. let me know if it works.
Try this:
class PatientsProvider with ChangeNotifier {
...
List<Patients> _patients = [];
// ///Getters
...
// Stream<List<Patients>> get getPatients => fireStoreService.getEntries();
List<Patients> get getPatients => _patients;
FirebaseFirestore _fs = FirebaseFirestore.instance;
StreamSubscription<QuerySnapshot> _stream;
PatientsProvider() {
_stream = _fs.collection('patients').snapshots().listen((snapshot) {
_patients = [];
snapshot.docs.forEach((queryDocumentSnapshot) {
_patients.add(Patients.fromJson(queryDocumentSnapshot.data()));
});
notifyListeners();
});
}
#override
void dispose() {
super.dispose();
_stream.cancel();
}
// savePatient(int agee, String usernamee, List<String> diseasess) {
...
// }
}
Then instead if creating a streambuilder, the provider will update the list when the data changes:
#override
Widget build(BuildContext context) {
PatientsProvider _provider = Provider.of<PatientsProvider >(context);
return Scaffold(
body: ListView.builder(
itemCount: _provider.getPatients.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
trailing: Icon(Icons.edit, color: Theme.of(context).accentColor),
title: Text('${...}'),
);
},
),
);
}
To get more information on the listener see this documentation:
https://firebase.google.com/docs/firestore/query-data/listen

Flutter refresh map after come back from second screen

I have a Flutter app which in home screen I use google map. At the begin, I call Firebase to take the places which I have already input. Then the user can add a new place if double in the map this lead him to SecondScreen. The user input title, story, and photo. I have and another screen where the user can view info for existing marker where can also delete it. My problem is when user input or delete marker and come back to the home page, in the map, the places are not refreshed and I see that the Firebase is not called again. How can I solve this problem? The Firebase is called in MapsDemo class
My code:
import 'dart:ui' as ui;
import 'dart:io';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:image_picker/image_picker.dart';
import 'package:uuid/uuid.dart';
import 'infopage.dart';
void main() {
GoogleMapController.init();
final size = MediaQueryData.fromWindow(ui.window).size;
final GoogleMapOverlayController controller =
GoogleMapOverlayController.fromSize(
width: size.width,
height: size.height,
);
final mapController = controller.mapController;
//// Set firebase https://www.youtube.com/watch?v=DqJ_KjFzL9I
//// TODO check if every time I come back the above commands call
// Firestore.instance.collection('Stories').snapshots().listen((data) =>
// data.documents.forEach((doc) =>
////Read all the markers from firebase and add them to map
//
// AddMarkers(mapController, ConvertCoordinates(doc["lat"], doc["lng"]),
// doc["title"], doc["story"], doc["url"])));
final Widget mapWidget = GoogleMapOverlay(controller: controller);
runApp(
MaterialApp(
home: new Scaffold(
appBar: AppBar(
title: TextField(
decoration: InputDecoration.collapsed(hintText: 'Search'),
),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.my_location),
onPressed: () async {
Position position = await Geolocator()
.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
// Get my current position
final location = LatLng(position.latitude, position.longitude);
mapController.markers.clear();
mapController.addMarker(MarkerOptions(
position: location,
infoWindowText: InfoWindowText("Here you are!", "Add me"),
visible: true));
mapController.animateCamera(
CameraUpdate.newLatLngZoom(location, 20.0),
);
},
),
],
),
body: MapsDemo(mapWidget, controller.mapController),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.my_location),
),
),
navigatorObservers: <NavigatorObserver>[controller.overlayController],
),
);
}
class MapsDemo extends StatelessWidget {
MapsDemo(this.mapWidget, this.controller);
final Widget mapWidget;
final GoogleMapController controller;
#override
Widget build(BuildContext context) {
// Set firebase https://www.youtube.com/watch?v=DqJ_KjFzL9I
// TODO check if every time I come back the above commands call
Firestore.instance.collection('Stories').snapshots().listen((data) =>
data.documents.forEach((doc) =>
//Read all the markers from firebase and add them to map
AddMarkers(controller, ConvertCoordinates(doc["lat"], doc["lng"]),
doc["title"], doc["story"], doc["url"])));
controller.onMarkerTapped.add((Marker marker) async {
//Marker listener open new page info page
String titlos = marker.options.infoWindowText.title;
if (titlos != "Here you are!") {
String story = marker.options.infoWindowText.snippet.split("?")[0];
String url = marker.options.infoWindowText.snippet.split("?")[1];
String realUrl = await makeRequest(url);
String downloadUrl =getDownloadUrl(realUrl,url);
Navigator.push(
// Parse title to next page/screen
context,
new MaterialPageRoute(
builder: (context) =>
new AboutPage(title: titlos, story: story, url: downloadUrl,)));
} else {
Navigator.push(
// Parse title to next page/screen
context,
new MaterialPageRoute(builder: (context) => new SecondScreen(
marker.options.position.latitude.toString(),
marker.options.position.longitude.toString())));
}
});
return Center(child: mapWidget);
}
}
LatLng ConvertCoordinates(String lat, String lng) {
// Convert strings coordinates to LatLng
return LatLng(double.parse(lat), double.parse(lng));
}
void AddMarkers(GoogleMapController map, LatLng coor, String title,
String story, String url) {
map.addMarker(MarkerOptions(
position: coor, infoWindowText: InfoWindowText(title, '$story'+'?'+'$url')));
}
Future<String> makeRequest(String n) async {
String baseUrl = 'https://firebasestorage.googleapis.com/v0/b/storymap-da000.appspot.com/o/';
String url = '$baseUrl' + '$n';
var client = new http.Client();
final response = await client.get(url);
return response.body;
}
String getDownloadUrl(String url, String name){
String baseUrl = 'https://firebasestorage.googleapis.com/v0/b/storymap-da000.appspot.com/o/';
String token = url.replaceAll("{", "").replaceAll("}", "").split('"downloadTokens": ')[1].replaceAll('"', '');
return '$baseUrl'+'$name'+"?alt=media&token="+'$token';
}
class SecondScreen extends StatelessWidget {
final String lat;
final String lng;
// final String image_name;
final titleC = TextEditingController();
final storyC = TextEditingController();
static final String image_name = Uuid().v1();
SecondScreen(this.lat, this.lng,);
Future getImage() async {
var image = await ImagePicker.pickImage(source: ImageSource.camera);
final StorageReference firebaseStorageRef =
FirebaseStorage.instance.ref().child(image_name);
final StorageUploadTask task =
firebaseStorageRef.putFile(image);
}
uploadFirebase(){
var map= {
"title":titleC.text,
"story":storyC.text,
"url":image_name,
"lat":lat,
"lng":lng
};
Firestore.instance.collection('Stories').document()
.setData(map);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new TextField (
controller: titleC,
),
new TextField(
controller: storyC,
),
new RaisedButton(
onPressed: () => getImage(),
child: new Text('Take photo'),
),
new RaisedButton(
onPressed: () => uploadFirebase(),
child: new Text('Confirm'),
)
])
),
);
}
}
[Edit]
I change my code to this,
import 'dart:ui' as ui;
import 'dart:io';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:image_picker/image_picker.dart';
import 'package:uuid/uuid.dart';
import 'infopage.dart';
void main() {
GoogleMapController.init();
final size = MediaQueryData.fromWindow(ui.window).size;
final GoogleMapOverlayController controller =
GoogleMapOverlayController.fromSize(
width: size.width,
height: size.height,
);
final mapController = controller.mapController;
//// Set firebase https://www.youtube.com/watch?v=DqJ_KjFzL9I
//// TODO check if every time I come back the above commands call
// Firestore.instance.collection('Stories').snapshots().listen((data) =>
// data.documents.forEach((doc) =>
////Read all the markers from firebase and add them to map
//
// AddMarkers(mapController, ConvertCoordinates(doc["lat"], doc["lng"]),
// doc["title"], doc["story"], doc["url"])));
final Widget mapWidget = GoogleMapOverlay(controller: controller);
runApp(
MaterialApp(
home: new Scaffold(
appBar: AppBar(
title: TextField(
decoration: InputDecoration.collapsed(hintText: 'Search'),
),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.my_location),
onPressed: () async {
Position position = await Geolocator()
.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
// Get my current position
final location = LatLng(position.latitude, position.longitude);
mapController.markers.clear();
mapController.addMarker(MarkerOptions(
position: location,
infoWindowText: InfoWindowText("Here you are!", "Add me"),
visible: true,draggable: true));
mapController.animateCamera(
CameraUpdate.newLatLngZoom(location, 20.0),
);
},
),
IconButton(
icon: const Icon(Icons.refresh),
onPressed: () {RefreshIt(mapController);},
)
],
),
body: _MapDemo(mapWidget:mapWidget, controller:controller.mapController),
),
navigatorObservers: <NavigatorObserver>[controller.overlayController],
),
);
}
class _MapDemo extends StatefulWidget{
final Widget mapWidget;
final GoogleMapController controller;
const _MapDemo({Key key, this.mapWidget, this.controller}) : super(key: key);
#override
MapsDemo createState() => MapsDemo(this.mapWidget, this.controller);
}
class MapsDemo extends State<_MapDemo> {
MapsDemo(this.mapWidget, this.controller);
final Widget mapWidget;
final GoogleMapController controller;
#override
Widget build(BuildContext context) {
// Set firebase https://www.youtube.com/watch?v=DqJ_KjFzL9I
controller.markers.clear();
// TODO check if every time I come back the above commands call
Firestore.instance.collection('Stories').snapshots().listen((data) =>
data.documents.forEach((doc) =>
//Read all the markers from firebase and add them to map
AddMarkers(controller, ConvertCoordinates(doc["lat"], doc["lng"]),
doc["title"], doc["story"], doc["url"])));
controller.onMarkerTapped.add((Marker marker) async {
//Marker listener open new page info page
String titlos = marker.options.infoWindowText.title;
if (titlos != "Here you are!") {
String story = marker.options.infoWindowText.snippet.split("?")[0];
String url = marker.options.infoWindowText.snippet.split("?")[1];
String realUrl = await makeRequest(url);
String downloadUrl =getDownloadUrl(realUrl,url);
Navigator.push(
// Parse title to next page/screen
context,
new MaterialPageRoute(
builder: (context) =>
new AboutPage(title: titlos, story: story, url: downloadUrl,)));
} else {
Navigator.push(
// Parse title to next page/screen
context,
new MaterialPageRoute(builder: (context) => new _SecondScreen(
lat:marker.options.position.latitude.toString(),
lng:marker.options.position.longitude.toString())));
}
});
return Center(child: mapWidget);
}
}
LatLng ConvertCoordinates(String lat, String lng) {
// Convert strings coordinates to LatLng
return LatLng(double.parse(lat), double.parse(lng));
}
void AddMarkers(GoogleMapController map, LatLng coor, String title,
String story, String url) {
map.addMarker(MarkerOptions(
position: coor, infoWindowText: InfoWindowText(title, '$story'+'?'+'$url')));
}
void RefreshIt(GoogleMapController mapController){
//TODO Refresh the map via this float button
}
Future<String> makeRequest(String n) async {
String baseUrl = 'https://firebasestorage.googleapis.com/v0/b/storymap-da000.appspot.com/o/';
String url = '$baseUrl' + '$n';
var client = new http.Client();
final response = await client.get(url);
return response.body;
}
String getDownloadUrl(String url, String name){
String baseUrl = 'https://firebasestorage.googleapis.com/v0/b/storymap-da000.appspot.com/o/';
String token = url.replaceAll("{", "").replaceAll("}", "").split('"downloadTokens": ')[1].replaceAll('"', '');
return '$baseUrl'+'$name'+"?alt=media&token="+'$token';
}
class _SecondScreen extends StatefulWidget{
final String lat;
final String lng;
const _SecondScreen({Key key, this.lat, this.lng}) : super(key: key);
#override
SecondScreen createState() => SecondScreen(this.lat, this.lng);
}
class SecondScreen extends State<_SecondScreen> {
final String lat;
final String lng;
// final String image_name;
final titleC = TextEditingController();
final storyC = TextEditingController();
static final String image_name = Uuid().v1();
SecondScreen(this.lat, this.lng,);
Future getImage() async {
var image = await ImagePicker.pickImage(source: ImageSource.camera);
final StorageReference firebaseStorageRef =
FirebaseStorage.instance.ref().child(image_name);
final StorageUploadTask task =
firebaseStorageRef.putFile(image);
}
uploadFirebase(){
var map= {
"title":titleC.text,
"story":storyC.text,
"url":image_name,
"lat":lat,
"lng":lng
};
Firestore.instance.collection('Stories').document()
.setData(map);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Input Screen"),
),
body: Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new TextField (
controller: titleC,
),
new TextField(
controller: storyC,
),
new RaisedButton(
onPressed: () => getImage(),
child: new Text('Take photo'),
),
new RaisedButton(
onPressed: () => uploadFirebase(),
child: new Text('Confirm'),
)
])
),
);
}
}
My firebase is shared with a website with the same concept, when I add something in the website the new marker is appeared in my Flutter app, but not when I delete a marker. On the other hand, when I add or remove marker from my Flutter app I don't get any refresh in my map... Any idea?
I set the mapStyle after resuming app from background and it worked for me:
mapController.setMapStyle("[]");
All of your widgets are Stateless which means they won't be able to update or change upon user interaction. This tutorial from the Flutter documentation goes through how to add interactivity to your app using Stateful widgets which will solve your problem.

Resources