Need help retrieving authorized user information Flutter Firestore - google-cloud-firestore

I have implemented in my flutter application Authentication via Firebase by login and password.
I also connected to a Firestore table with user data.
I only need to show the authenticated user's data by their ID, which are assigned to the other data tables.
How to link e.g. Users id: 1 with Tasks User id:1 ?
home_page.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:loginui/read_data/get_user_name.dart';
class MyTaskPage extends StatefulWidget {
const MyTaskPage({Key? key}) : super(key: key);
#override
State<MyTaskPage> createState() => _MyTaskPageState();
}
class _MyTaskPageState extends State<MyTaskPage> {
final user = FirebaseAuth.instance.currentUser!;
// document IDs
List<String> docIDs = [];
// get docIDs
Future getDocId() async {
await FirebaseFirestore.instance
.collection('tasks')
.orderBy('name', descending: true)
// .where('age', isGreaterThan: 44)
.get()
.then((snapshot) => snapshot.docs.forEach((document) {
print(document.reference);
docIDs.add(document.id);
}));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurple[200],
centerTitle: true,
actions: [
GestureDetector(
onTap: () {
setState(() {
FirebaseAuth.instance.signOut();
});
},
child: Icon(Icons.logout),
),
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: FutureBuilder(
future: getDocId(),
builder: (context, snapshot) {
return ListView.builder(
itemCount: docIDs.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ListTile(
title: GetUserName(documentId: docIDs[index]),
tileColor: Colors.grey[200],
),
);
},
);
},
),
),
],
),
),
);
}
}
get_user_name.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class GetUserName extends StatelessWidget {
final String documentId;
GetUserName({required this.documentId});
#override
Widget build(BuildContext context) {
// get the collection
CollectionReference users = FirebaseFirestore.instance.collection('tasks');
return FutureBuilder<DocumentSnapshot>(
future: users.doc(documentId).get(),
builder: ((context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data =
snapshot.data!.data() as Map<String, dynamic>;
return Text(
'${data['name']}',
overflow: TextOverflow.ellipsis,
softWrap: true,
);
}
return Text('Loading...');
}),
);
}
}

final _auth = FirebaseAuth.instance;
final _firestore = FirebaseFirestore.instance;
if (_auth.currentUser != null) {
// user is signed in
final uid = _auth.currentUser!.uid;
final userData = await _firestore.collection('users').doc(uid).get();
final taskData = await _firestore.collection('tasks').doc(uid).get();
// handle the data
}

Related

How to use a async function inside a ListView.builder?

Is there anyway to get a future when displaying a list?
I have list with two user id's ( one of them is the userlogged in, the other one is the user to chat with ).
my goal is to get and display the other users name in the chat.
the issue I am running into, is that you cant do async functions within the list
how can i fix this?
typedef JobCallback = void Function(CloudChat job);
class ChatsListWidget extends StatelessWidget {
final Iterable<CloudChat> cloudChats; // list of jobs
final JobCallback onDeleteJob;
final JobCallback onTap;
String get userId => AuthService.firebase().currentUser!.id;
const ChatsListWidget({
Key? key,
required this.cloudChats,
required this.onDeleteJob,
required this.onTap,
}) : super(key: key);
Future getOtherUsersName(userIdsArr) async {
String? otherUserInChatId;
for (var _userId in userIdsArr) {
if (_userId != userId) {
otherUserInChatId = _userId;
}
}
var userData = await FirebaseFirestore.instance
.collection('user')
.doc(otherUserInChatId)
.get();
return userData[userFirstNameColumn];
}
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: cloudChats.length,
itemBuilder: (context, index) {
final job = cloudChats.elementAt(index);
var otherUserName = await getOtherUsersName(job.userIdsArr);
;
return ListTile(
onTap: () {
onTap(job);
},
title: Text(
otherUserName,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
//
},
icon: const Icon(Icons.delete),
),
);
},
);
}
}
I tried the following code as suggested but did not work::
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import '../../services/auth/auth_service.dart';
import '../../services/cloud/cloud_chat.dart';
import '../../services/cloud/cloud_storage_constants.dart';
typedef JobCallback = void Function(CloudChat job);
class ChatsListWidget extends StatelessWidget {
final Iterable<CloudChat> cloudChats; // list of jobs
final JobCallback onDeleteJob;
final JobCallback onTap;
String get userId => AuthService.firebase().currentUser!.id;
const ChatsListWidget({
Key? key,
required this.cloudChats,
required this.onDeleteJob,
required this.onTap,
}) : super(key: key);
Future getOtherUsersName(userIdsArr) async {
String? otherUserInChatId;
for (var _userId in userIdsArr) {
if (_userId != userId) {
otherUserInChatId = _userId;
}
}
var userData = await FirebaseFirestore.instance
.collection('user')
.doc(otherUserInChatId)
.get();
return userData[userFirstNameColumn];
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: getOtherUsersName(job.userIdsArr),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: cloudChats.length,
itemBuilder: (context, index) {
final job = cloudChats.elementAt(index);
return ListTile(
onTap: () {
onTap(job);
},
title: Text(
otherUserName,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
//
},
icon: const Icon(Icons.delete),
),
);
},
);
} else if (snapshot.connectionState == ConnectionState.waiting) {
Center(
child: CircularProgressIndicator(),
);
}
return Center(
child: Text("Empty"),
);
},
);
}}
The simple and short answer is to use FutureBuilder which take future as named parameter and give you the result in builders parameters generally know as snapshot.
First of all wrap your list view with future builder :
FutureBuilder(
future: "you future funtion here",
builder: (context, snapshot) {
return ListView.builder(itemBuilder: itemBuilder);
}
)
now you can give future funtion , in your case it is
FutureBuilder(
future: getOtherUsersName(job.userIdsArr),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: cloudChats.length,
itemBuilder: (context, index) {
final job = cloudChats.elementAt(index);
return ListTile(
onTap: () {
onTap(job);
},
title: Text(
otherUserName,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
//
},
icon: const Icon(Icons.delete),
),
);
},
);
} else if (snapshot.connectionState == ConnectionState.waiting) {
Center(
child: CircularProgressIndicator(),
);
}
return Center(
child: Text("Empty"),
);
},
);
And remember to use snapshot if conditions for loading and empty data
complete code
import 'package:flutter/material.dart';
typedef JobCallback = void Function(CloudChat job);
class ChatsListWidget extends StatelessWidget {
final Iterable<CloudChat> cloudChats; // list of jobs
final JobCallback onDeleteJob;
final JobCallback onTap;
String get userId => AuthService.firebase().currentUser!.id;
const ChatsListWidget({
Key? key,
required this.cloudChats,
required this.onDeleteJob,
required this.onTap,
}) : super(key: key);
Future getOtherUsersName(userIdsArr) async {
String? otherUserInChatId;
for (var _userId in userIdsArr) {
if (_userId != userId) {
otherUserInChatId = _userId;
}
}
var userData = await FirebaseFirestore.instance
.collection('user')
.doc(otherUserInChatId)
.get();
return userData[userFirstNameColumn];
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: getOtherUsersName(job.userIdsArr),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: cloudChats.length,
itemBuilder: (context, index) {
final job = cloudChats.elementAt(index);
return ListTile(
onTap: () {
onTap(job);
},
title: Text(
otherUserName,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
//
},
icon: const Icon(Icons.delete),
),
);
},
);
} else if (snapshot.connectionState == ConnectionState.waiting) {
Center(
child: CircularProgressIndicator(),
);
}
return Center(
child: Text("Empty"),
);
},
);
}}
HopeFully It will help you.

How do I get data from my firestore document as a variable and use that to direct the path my stream builder uses in flutter

The code below is what I am trying now. The page works does everything I need but now I need this database reference to use the loanuid, clientuid, and companyName to get to the right directory.
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('prosperitybank')
.doc('OHViYK8Zz6XfKGJsSXRL')
.collection('Project Information')
.snapshots()```
I need it from my collection.(userCreationRef).doc(loggedinuid) as shown in the picture. I can not figure out how to do this without the stream builders interfering any help would be greatly appreciated. I have tried to using this to help but it did not How can you nest StreamBuilders in Flutter?. I also tried looking at the documentation here https://firebase.flutter.dev/docs/firestore/usage/.
Picture of Document I need data fields from
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:photoloanupdated/screens/mains/viewproperties.dart';
import 'package:provider/provider.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
final FirebaseAuth auth = FirebaseAuth.instance;
final user = auth.currentUser;
final uid = user?.uid;
var users = FirebaseFirestore.instance.collection('userCreationRequests');
var companyname = "";
return Scaffold(
appBar: AppBar(
title: Text(companyname),
),
body:
FutureBuilder<DocumentSnapshot>(
future: users.doc(uid).get(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.hasData && !snapshot.data!.exists) {
return Text("Document does not exist");
}
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data =
snapshot.data!.data() as Map<String, dynamic>;
return Text("Full Name: ${data['companyName']} ${data['last_name']}");
}
return Text("loading");
},
);
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection('prosperitybank')
.doc('OHViYK8Zz6XfKGJsSXRL')
.collection('Project Information')
.snapshots(), //key spot fV or email fix
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data?.docs.length,
itemBuilder: (BuildContext context, int index) {
QueryDocumentSnapshot<Object?>? documentSnapshot =
snapshot.data?.docs[index];
//for date/time DateTime mydateTime = documentSnapshot['created'].toDate();
return InkWell(
onTap: () {
Navigator.of(context)
.push(
MaterialPageRoute(
builder: (context) => ViewProperties(documentSnapshot,
snapshot.data?.docs[index].reference)),
)
.then((value) {
setState(() {});
});
},
child: Card(
child: Container(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"${documentSnapshot!['address']}",
style: TextStyle(
fontSize: 24.0,
fontFamily: "lato",
fontWeight: FontWeight.bold,
color: Colors.black),
),
Container(
alignment: Alignment.centerRight,
child: Text(
"${documentSnapshot!['projectcomplete'].toString() + "% Complete"}",
// for mydateTime.toString(),
style: TextStyle(
fontSize: 17.0,
fontFamily: "lato",
color: Colors.black87),
),
)
],
),
),
),
),
);
},
);
} else {
return Center(
child: Text("Loading..."),
);
}
},
),
);
}
}
String uuid;
Future<List<Map<String, dynamic>>> _onQuery() {
Future<List<Map<String, dynamic>>> res;
if (uuid != null) {
res = future.get().then((v) => v.docs
.map((e) => e.data())
.where((e) =>
e['uuid'].toLowerCase().contains(uuid))
.toList());
} else {
res = future.get().then((v) => v.docs.map((e) => e.data()).toList());
}
setState(() {});
return res;
}
now you can use _onQuery as stream.

Getting data from a document in FireBase and adding them into a map

I am trying to transfer my data from FireBase Collection to a map. Then, the map data will go into MultiSelectBottomSheetField.
Problems: I am getting "Instance of '_JsonQueryDocumentSnapshot'" instead of 'Home' for example.
I still not getting the list of context from collection into MultiSelectItem
Also, I have noticed that when I start the app, the MultiSelectionItem is empty. It is displaying "Instance of '_JsonQueryDocumentSnapshot'" when I display the main view a second time. I guess that a SetState is probably missing somewhere. But as I can not write set state in a constructor, I am puzzled.
This is driving me nuts as I do not find where the problem is coming from.
Many thanks for your help.
import 'package:flutter_swipe_action_cell/core/cell.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/foundation.dart';
import 'package:multi_select_flutter/bottom_sheet/multi_select_bottom_sheet_field.dart';
import 'package:multi_select_flutter/util/multi_select_item.dart';
String inboxTaskDisplayed='';
int nbRecord=0;
var taskSelectedID;
var taskDone;
//------TEST
class ContextExisting {
final int id;
final String name;
ContextExisting({
this.id,
this.name,
});
}
List<ContextExisting> _contexts = [];
List <ContextExisting>allMyContext=[];
TextEditingController passController = new TextEditingController();
//-----------------
var documentID;
var textController = TextEditingController();
var popUpTextController = TextEditingController();
//_-----------------
class Inbox_Test_For_Chip_Trial extends StatefulWidget {
final String screenSelected;
final String titlePage;
Inbox_Test_For_Chip_Trial(Key key, {#required this.screenSelected, #required this.titlePage,}) : super(key: key);
#override
_Inbox_Test_For_Chip_TrialState createState() => _Inbox_Test_For_Chip_TrialState(screenSelected, titlePage);
}
class _Inbox_Test_For_Chip_TrialState extends State<Inbox_Test_For_Chip_Trial> {
GlobalKey<FormState> _inboxFormKey = GlobalKey<FormState>();
String screenSelected;
String titlePage;
_Inbox_Test_For_Chip_TrialState(this.screenSelected, this.titlePage,);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: new Text(titlePage + ' ('+nbRecord.toString()+')'),
actions: <Widget>[
],
),
backgroundColor: Colors.white,
body: Container(
height: 250,
child: Column(
//mainAxisAlignment: MainAxisAlignment.center,
children: [
//FOR CONTEXT
Flexible(child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('Users')
.doc(FirebaseAuth.instance.currentUser.uid)
.collection('contexts')
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
else {
var docs = snapshot.data.docs;
print('docs');
print (docs[2].id);
print(snapshot.data.docs.length);
int nbContext = snapshot.data.docs.length;
for (int i=0;i<nbContext; i++) {
_contexts.addAll([ContextExisting (id:i, name:snapshot.data.toString())]);
print(_contexts);
}
return Container(
height: MediaQuery.of(context).size.height * .78,
width: MediaQuery.of(context).size.width,
child: ListView(
children: snapshot.data.docs.map((document) {
return Wrap(
children: [Card(
child: SwipeActionCell(
key: ObjectKey(document['context_Name']),
trailingActions: <SwipeAction>[
],
child: ListTile(
trailing: IconButton(
icon: Icon(Icons.keyboard_arrow_right),
onPressed: () async {
taskSelectedID = FirebaseFirestore
.instance
.collection('Users')
.doc(
FirebaseAuth.instance.currentUser
.uid)
.collection('contexts')
.doc(document.id).toString();
}
),
leading: ConstrainedBox(
constraints: BoxConstraints(
minWidth: 30,
minHeight: 35,
maxWidth: 30,
maxHeight: 35,
),
//InkWell(child: Icon(Icons.check_box_outline_blank),
),
title: Text(
document['context_Name'],
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
),
),
]
);
}).toList(),
),
);
}
}),),
Column(children:[
TestWidgetContext(),
]), //MyHomePage())
],
),
),
//bottomNavigationBar: MyBottomAppBar(), //PersistentBottomNavBar(),
);
}
class TestWidgetContext extends StatefulWidget {
TestWidgetContext({Key key}) : super(key: key);
#override
_TestWidgetContextState createState() => _TestWidgetContextState();
}
class _TestWidgetContextState extends State<TestWidgetContext> {
List itemsContext;
List<ContextExisting> _selectedContext5 = [];
final _itemsContext = _contexts
.map((context) => MultiSelectItem<ContextExisting>(context, context.name))
.toList();
#override
void initState() {
_selectedContext5 = _contexts;
super.initState();
}
#override
Widget build(BuildContext context) {
return Column(
children: [
MultiSelectBottomSheetField(
buttonText: Text("Contexts"),
onConfirm: (val2) {
},
items: _itemsContext,
// initialValue:
// _itemsContext,
),
],
);
}
}
Since the code has a lot of errors, I am writing down my findings.
allMyContext is a list and if you wish to add elements to it you should be wring it as
allMyContext.add(ContextExisting (id:i, name:doc.name));
instead of List<allMyContext> = ContextExisting (id:i, name:doc.name)
Insde the on pressed
taskSelectedID = (document.id).toString();
since you already have taken a document you don't have to query it again
final doc = FirebaseFirestore.instance.collection('users').doc('contexts').get();
and
FirebaseFirestore.instance.collection('Users').doc(FirebaseAuth.instance.currentUser.uid).collection('contexts').snapshots(),
These two are contradictory. Is contexts a collection or a document?
Problem solved.
child: Column(
//mainAxisAlignment: MainAxisAlignment.center,
children: [
//FOR CONTEXT
Flexible(child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('Users')
.doc(FirebaseAuth.instance.currentUser.uid)
.collection('contexts')
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
} else if (snapshot.hasData) {
// if connectionState is waiting
if (snapshot.connectionState == ConnectionState.waiting)
{
return Center(child: CircularProgressIndicator());
} else {
for (int i=0;i<snapshot.data.docs.length;i++){
DocumentSnapshot snap = snapshot.data.docs[i];
_contexts.add(snap['context_Name']);
}
}
}
// return widgets and use data
return Column(children:[
TestWidgetContext(),
]); //MyHomePage())

How can i pass snapshot data from futurebuilder to another futurebuilder in the same page?

I'm new to the flutter world and mobile app development and struggling with how I should pass data throughout my app. This is my code, How can I pass snapshot data from futurebuilder to another futurebuilder on the same page? help, please
**Widget _buildProgrammCard()**
From this widget Card I need to pass the location id which is in the futurebuilder to another futurebuilder.
Widget _buildProgrammCard() {
return Container(
height: 90,
child:
Card(
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 4,
margin: EdgeInsets.fromLTRB(14, 0, 14, 14),
child:
FutureBuilder(
future: databaseHelper2.Lastlocation(),
builder: (context,snapshot) {
if (snapshot.hasError)
{
print(snapshot.error);
print("there is problem");
}
return snapshot.hasData
? Text("Location :" +snapshot.data.id)
: Center(child: CircularProgressIndicator(
),
);
}
),
),
);
}
Widget build(BuildContext context)
And this is the second Widget that I need to pass the location id into it from another widget.
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[100],
body: FutureBuilder(
future: databaseHelper2.Getweither(location_id),
builder: (context,snapshot) {
if (snapshot.hasError)
{
print(snapshot.error);
print("there is problem !");
}
return snapshot.hasData
? ItemList(list: snapshot.data)
: Center(child: CircularProgressIndicator(
),
);
}
),
);
}
Flutter rebuilds widgets often so FutureBuilder shouldn't call a future function directly. (A widget may call its build function up to 60 times a second.)
Instead a FutureBuilder should only receive a future value from an async function called elsewhere.
In a StatefulWidget, the most common place to initiate long-running operations is in its initState() method.
The location data, retrieved during the first Widget initState, can be passed to the second widget, just like a regular constructor argument.
You'll access it in the 2nd widget's State class with widget.locationId.
import 'package:flutter/material.dart';
class FirstFuturePage extends StatefulWidget {
#override
State<StatefulWidget> createState() => FirstFutureState();
}
class FirstFutureState extends State<FirstFuturePage> {
Future<int> locationId = Future.value(-1);
#override
void initState() {
// TODO: implement initState
super.initState();
someAsyncCall();
}
Future<void> someAsyncCall() async {
// just returns the number 0 after 2 seconds & assigns it to "locationId" var
locationId = Future.delayed(Duration(seconds: 2), () => 0);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: FutureBuilder<int>(
future: locationId,
builder: (context, snapshot) {
int _locationId = snapshot.data;
if (snapshot.hasData)
return SecondWidget(_locationId);
return Text('Looking up location...');
},
),
),
),
);
}
}
class SecondWidget extends StatefulWidget {
final int locationId;
SecondWidget(this.locationId);
#override
_SecondWidgetState createState() => _SecondWidgetState();
}
class _SecondWidgetState extends State<SecondWidget> {
Future<String> weatherData = Future.value('Unknown');
#override
void initState() {
super.initState();
loadWeather(widget.locationId); // Use the locationId passed into widget
}
/// Takes locationId from First widget and looks up weather data for location
Future<void> loadWeather(int locationId) async {
List<String> weatherDataStore = List<String>.from(['Rainy', 'Sunny']);
weatherData = Future.delayed(
Duration(seconds: 2), () => weatherDataStore[locationId]
);
}
#override
Widget build(BuildContext context) {
int _locId = widget.locationId;
return FutureBuilder<String>(
future: weatherData,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text('Weather for location $_locId is: ${snapshot.data}');
}
return Text('Loading Weather...');
},
);
}
}
State Management Solutions
When you get tired of passing values around like in the above example, you can use a State Management package or create your own that suits your needs.
Here's a nice overview from Jeff Delaney about various options:
https://fireship.io/lessons/flutter-state-management-guide/
And also check out Get which isn't mentioned in the above:
https://pub.dev/packages/get
Some of the above State management solutions (e.g. Provider) help you use Flutter-native state functionality correctly (because its rather complicated), while others completely avoid that and provide a framework separate from the Widget lifecycle (e.g. Get).
Thanks Baker for your response but not exactly what i meant
these are my two futures and my class
This is my future that returns the Location from her i need to pass the location id to the another future
Future<Location> Lastlocation() async {
final prefs = await SharedPreferences.getInstance();
final key = 'token';
final value = prefs.get(key) ?? 0;
String myUrl = "$serverUrl/location/getlastlocation?token=" + value;
http.Response response = await http.get(
myUrl,
headers: {
'Accept': 'application/json',
//'Authorization': 'token $value'
},
);
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
return Location.fromJson(json.decode(response.body));
} else {
// then throw an exception.
throw Exception('Failed to load album');
}
}
This is my future that returns List of weather that depends on location id
Future<List> Getweither(String ID) async {
final prefs = await SharedPreferences.getInstance();
final key = 'token';
final value = prefs.get(key) ?? 0;
String myUrl = "$serverUrl/sensors/getDeviceByid/$ID?token=" + value;
http.Response response = await http.get(myUrl,
headers: {
'Accept': 'application/json',
});
print("myUrldevice :"+myUrl);
print("status :"+response.statusCode.toString());
return json.decode(response.body);
}
This is my class Location
// To parse this JSON data, do
//
// final location = locationFromJson(jsonString);
import 'dart:convert';
List<Location> locationFromJson(String str) => List<Location>.from(json.decode(str).map((x) => Location.fromJson(x)));
String locationToJson(List<Location> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Location {
Location({
this.automaticIrrigation,
this.coordinates,
this.createdDate,
this.sensorIds,
this.id,
this.siteName,
this.description,
this.v,
});
bool automaticIrrigation;
List<double> coordinates;
DateTime createdDate;
List<String> sensorIds;
String id;
String siteName;
String description;
int v;
factory Location.fromJson(Map<String, dynamic> json) => Location(
automaticIrrigation: json["AutomaticIrrigation"],
coordinates: List<double>.from(json["Coordinates"].map((x) => x.toDouble())),
createdDate: DateTime.parse(json["Created_date"]),
sensorIds: List<String>.from(json["Sensor_ids"].map((x) => x)),
id: json["_id"],
siteName: json["SiteName"],
description: json["Description"],
v: json["__v"],
);
Map<String, dynamic> toJson() => {
"AutomaticIrrigation": automaticIrrigation,
"Coordinates": List<dynamic>.from(coordinates.map((x) => x)),
"Created_date": createdDate.toIso8601String(),
"Sensor_ids": List<dynamic>.from(sensorIds.map((x) => x)),
"_id": id,
"SiteName": siteName,
"Description": description,
"__v": v,
};
}
and this is my homePage
import 'dart:convert';
import 'dart:developer';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:sidebar_animation/Services/DataHelpers.dart';
import 'package:sidebar_animation/sidebar/sidebar_layout.dart';
import '../bloc.navigation_bloc/navigation_bloc.dart';
import 'package:sidebar_animation/constants.dart';
import 'package:flutter/gestures.dart';
import 'package:sidebar_animation/bloc.navigation_bloc/navigation_bloc.dart';
class HomePage extends StatelessWidget with NavigationStates {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
DatabaseHelper2 databaseHelper2 = new DatabaseHelper2();
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[100],
body: ListView(
FutureBuilder(
future: databaseHelper2.Getweither(location_id),
builder: (context,snapshot) {
if (snapshot.hasError)
{
print(snapshot.error);
print("there is problem !");
}
return snapshot.hasData
? ItemList(list: snapshot.data)
: Center(child: CircularProgressIndicator(
),
);
}
),
);
}
Widget _buildProgrammCard() {
return Container(
height: 90,
child:
Card(
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 4,
margin: EdgeInsets.fromLTRB(14, 0, 14, 14),
child:
FutureBuilder(
// future: databaseHelper.getData(),
future: databaseHelper2.Lastlocation(),
builder: (context,snapshot) {
if (snapshot.hasError)
{
print(snapshot.error);
print("mochkla lenaa *");
}
return snapshot.hasData
? Text("Location :" +snapshot.data.siteName)
: Center(child: CircularProgressIndicator(
),
);
}
),
),
);
}
class ItemList extends StatelessWidget{
List list;
ItemList({this.list});
ScrollController _controller = new ScrollController();
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: list == null ? 0 : list.length,
scrollDirection: Axis.horizontal,
itemExtent: 190.0,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 0, 14),
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
item.storyUrl,
),
fit: BoxFit.cover,
colorFilter: ColorFilter.mode(
Colors.black26,
BlendMode.darken,
),
),
borderRadius: BorderRadius.circular(10.0),
color: Colors.grey,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
"temp :",
style: TextStyle(color: Colors.white),
),
),
Padding(
padding: EdgeInsets.only(left: 24),
child:
Text(
list[i]['Weither']['Temp'],
),
),
],
),
),
);
},
),
}
}
Finaly i need to get the location id from the first future that return Location to the second future Getweither(String ID) .

Null check operator used on null value

I need to grab a list of all messages in the database where the level is less than or equal to the user's current level. To do this I am attempting to use a nested streambuilder. First one pulls the user info, then I use the user level to make the second query. My problem is I get an error.
Null check operator used on null value
I do not understand this error. I checked firestore to see that there is data in the collection, and I also made sure to put the proper rules in place. I've tried several variations of this code and this is the only one so far that at least doesn't give me an error in the emulator. My emulator shows the appbar and the body is blank.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import '../screens/welcome_screen.dart';
class MessagesScreen extends StatefulWidget {
static const String id = 'messages_screen';
#override
_MessagesScreenState createState() => _MessagesScreenState();
}
class _MessagesScreenState extends State<MessagesScreen> {
final _firestore = FirebaseFirestore.instance;
final _auth = FirebaseAuth.instance;
User loggedInUser;
int _userCurrentLevel;
#override
void initState() {
super.initState();
getCurrentUser();
}
void getCurrentUser() {
try {
final user = _auth.currentUser;
if (user != null) {
loggedInUser = user;
}
} catch (e) {
print(e);
}
}
getMessages(AsyncSnapshot<QuerySnapshot> snapshot2) {
return snapshot2.data.docs
.map((doc) => new ListTile(title: Text(doc['from']), subtitle: Text(doc['text'])))
.toList();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text('Darker Slate'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.chat),
tooltip: 'Messages',
onPressed: () {},
),
IconButton(
icon: const Icon(Icons.exit_to_app),
tooltip: 'Log Out',
onPressed: () {
_auth.signOut();
Navigator.pushNamed(context, WelcomeScreen.id);
},
),
],
),
body: StreamBuilder<DocumentSnapshot>(
stream: _firestore.collection('users')
.doc(_auth.currentUser.uid)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.red[900],
),
);
}
_userCurrentLevel = snapshot.data['userlevel'];
return StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('messages')
.where('level', isLessThanOrEqualTo: _userCurrentLevel).snapshots(),
builder: (context, snapshot2) {
if (!snapshot2.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.red[900],
),
);
}
return Column(
children: [
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: snapshot2.data.docs.length,
itemBuilder: (_, index) {
return new ListView(children: getMessages(snapshot2));
}),
],
);
}
);
}),
);
}
}