Flutter Future<Object> not return - flutter

Becoming mad about a simple piece of code...
I have a class:
class Monkey {
final String uid;
final String email;
final String password;
final int registrationMethod;
final int accountCreationTime; //* in milliseconds
final String name;
final String nickname;
final int birthday; //* in milliseconds
final String phone;
final String countryCode;
final String codiceComune;
final String comune;
final String provincia;
final String regione;
final String cap;
final String sigla;
final String zona;
final String codiceCatastale;
final int popolazione;
final bool isRegistered;
final bool shareName;
final bool acceptedRules;
final String picUrl;
final int
userPicType; //* 1 - Email / 2 - Google / 3 - Facebook / 4 - Apple / 5 - File
const Monkey(
this.uid,
this.email,
this.password,
this.registrationMethod,
this.accountCreationTime,
this.name,
this.nickname,
this.birthday,
this.phone,
this.countryCode,
this.codiceComune,
this.comune,
this.provincia,
this.regione,
this.cap,
this.sigla,
this.zona,
this.codiceCatastale,
this.popolazione,
this.isRegistered,
this.shareName,
this.acceptedRules,
this.picUrl,
this.userPicType,
);
}
I have a variable:
static Monkey monkey = const Monkey(
'uid',
'email',
'password',
0,
0,
'name',
'nickname',
0,
'phone',
'countryCode',
'codiceComune',
'comune',
'provincia',
'regione',
'cap',
'sigla',
'zona',
'codiceCatastale',
0,
false,
false,
false,
'picUrl',
0);
I have a method to fill the variable:
Future<Monkey?> getMonkey() async {
try {
await _firestore
.collection('users')
.doc(getUID())
.get()
.then((DocumentSnapshot documentSnapshot) {
Map<String, dynamic> data =
documentSnapshot.data() as Map<String, dynamic>;
if (data.isNotEmpty) {
if (kDebugMode) {
print("Point 1");
}
return Monkey(
data['uid'],
data['email'],
data['password'],
data['registrationMethod'],
data['accountCreationTime'],
data['name'],
data['nickname'],
data['birthday'],
data['phone'],
data['countryCode'],
data['codiceComune'],
data['comune'],
data['provincia'],
data['regione'],
data['cap'],
data['sigla'],
data['zona'],
data['codiceCatastale'],
data['popolazione'],
data['isRegistered'],
data['shareName'],
data['acceptedRules'],
data['picUrl'],
data['userPicType']);
} else {
if (kDebugMode) {
print(
"La lettura di monkey non ha restituito dati, elsedella lettura Monkey.");
}
return null;
}
});
} catch (err) {
if (kDebugMode) {
print("Errore durante la lettura di Monke: " + err.toString());
}
return null;
}
if (kDebugMode) {
print(
"Point 2");
}
return null;
}
This is my execution:
Variables.monkey = (await _firebase.getMonkey())!;
As I can see my code fire Print Point 1 but also Print Point 2.
I printed data and it is filled successfully.
But I receive this error:
[VERBOSE-2:ui_dart_state.cc(209)] Unhandled Exception: Null check operator used on a null value
#0 _RegistrationScreenState.registerUser
package:whybye/screens/registration_screen.dart:345
edit:
Just removed any 'final' from Class Monkey, however same result.

The error is here:
Future<Monkey?> getMonkey() async {
try {
await _firestore
.collection('users')
.doc(getUID())
.get()
.then((DocumentSnapshot documentSnapshot) {
Map<String, dynamic> data =
documentSnapshot.data() as Map<String, dynamic>;
if (data.isNotEmpty) {
if (kDebugMode) {
print("Point 1");
}
return Monkey(
data['uid'],
data['email'],
data['password'],
data['registrationMethod'],
data['accountCreationTime'],
data['name'],
data['nickname'],
data['birthday'],
data['phone'],
data['countryCode'],
data['codiceComune'],
data['comune'],
data['provincia'],
data['regione'],
data['cap'],
data['sigla'],
data['zona'],
data['codiceCatastale'],
data['popolazione'],
data['isRegistered'],
data['shareName'],
data['acceptedRules'],
data['picUrl'],
data['userPicType']);
} else {
if (kDebugMode) {
print(
"La lettura di monkey non ha restituito dati, elsedella lettura Monkey.");
}
return null;
}
});
} catch (err) {
if (kDebugMode) {
print("Errore durante la lettura di Monke: " + err.toString());
}
return null;
}
if (kDebugMode) {
print(
"Point 2");
}
return null;
}
Where return Monkey is inside another process (await _firestore).
This mean the code is ok but I had to add:
Monkey monkey;
monkey = await _firestore...
return monkey(...)...
and outside the _firestore process return the real monkey...
Before I found the solution I tried tons of code and finally I switched to String:
Future<String> getMonkey() async {
String res;
try {
res = await _firestore
.collection('users')
.doc(getUID())
.get()
.then((DocumentSnapshot documentSnapshot) {
Map<String, dynamic> data =
documentSnapshot.data() as Map<String, dynamic>;
if (data.isNotEmpty) {
if (kDebugMode) {
print("I dati di Monkey non sono vuoti: ");
}
Monkey.uid = data['uid'];
Monkey.email = data['email'];
Monkey.password = data['password'];
Monkey.registrationMethod = data['registrationMethod'];
Monkey.accountCreationTime = data['accountCreationTime'];
Monkey.name = data['name'];
Monkey.nickname = data['nickname'];
Monkey.birthday = data['birthday'];
Monkey.phone = data['phone'];
Monkey.countryCode = data['countryCode'];
Monkey.codiceComune = data['codiceComune'];
Monkey.comune = data['comune'];
Monkey.provincia = data['provincia'];
Monkey.regione = data['regione'];
Monkey.cap = data['cap'];
Monkey.sigla = data['sigla'];
Monkey.zona = data['zona'];
Monkey.codiceCatastale = data['codiceCatastale'];
Monkey.popolazione = data['popolazione'];
Monkey.isRegistered = data['isRegistered'];
Monkey.shareName = data['shareName'];
Monkey.acceptedRules = data['acceptedRules'];
Monkey.picUrl = data['picUrl'];
Monkey.userPicType = data['userPicType'];
return 'success';
} else {
if (kDebugMode) {
print(
"La lettura di monkey non ha restituito dati, elsedella lettura Monkey.");
}
return 'error';
}
});
} catch (err) {
if (kDebugMode) {
print("Errore durante la lettura di Monkey: " + err.toString());
}
return 'error';
}
if (res == 'success') {
return 'success';
} else {
return 'error';
}
}
As you can see the real Return function is at bottom:
if (res == 'success') {
return 'success';
} else {
return 'error';
}

This error occurs when you use a bang operator (!) on a nullable instance which wasn't initialized.
Replace your execution with this:
var monkey = await _firebase.getMonkey();
if(monkey != null){
Variables.monkey = monkey;
}
I hope it would help you.

Related

Make a stream wait for data to assign a late property

I have following code.
I need to assign a late userName (not stored in database BID table) from the Bid Object that i retreive from the firestore with a stream.
The userName can be found in another table in the database (USER table).
I need to connect those 2 all while a streambuilder is building with BID object stream coming in.
Repository
final _firestoreDB = FirebaseFirestore.instance;
Future<String> getDbUserNameFromDbUserID({required String dbUserID}) async {
try {
final docUser = _firestoreDB.collection('users').doc(dbUserID);
final snapshot = await docUser.get();
if (snapshot.exists) {
if (snapshot.data() != null){
return DbUser.fromJson(snapshot.data()!).userName;
}
}
throw Exception("getDBUserByDBUserId() No fireStore userName found");
} catch (e) {
throw Exception(e);
}
}
Stream<List<Bid>> getAllBidsByItemId({required String itemID}) {
try {
return _firestoreDB
.collection('bids')/*.orderBy('timestamp')*/
.where('itemID', isEqualTo: itemID)
.snapshots()
.map((snapshot) =>
snapshot.docs.map((doc) {
Bid bid = Bid.fromJson(doc.data());
bid.bidId = doc.id;
**bid.userName = await getDbUserNameFromDbUserID( dbUserID: bid.bidderID); ///????**
return bid;
}).toList());
} catch (e) {
throw Exception(e);
}
}
model
class Bid {
late String bidId;
**late String userName;**
final String bidderID;
final String itemID;
final double price;
final DateTime timestamp;
Bid(
{
required this.bidderID,
required this.itemID,
required this.price,
required this.timestamp});
Map<String, dynamic> toJson() => {
'bidderID': bidderID,
'itemID': itemID,
'price': price,
'timestamp': timestamp,
};
static Bid fromJson(Map<String, dynamic> json) => Bid(
bidderID: json['bidderID'],
itemID: json['itemID'],
price: json['price'],
timestamp: (json['timestamp'] as Timestamp).toDate(),
);
}
How can I assign the late String userName when the stream gets the objects from the firestore?
Whats the best practice to do this? I assume this is not the best way to go about it?
I am using Bloc and Firestore Firebase
Thank you
SOLUTION
Stream<List<Bid>> getAllBidsByItemId({required String itemID}) async* {
try {
yield* _firestoreDB
.collection('bids')
.where('itemID', isEqualTo: itemID)
.snapshots()
.asyncMap<List<Bid>>((event) async {
List<Bid> bids = [];
for (var doc in event.docs) {
try {
Bid bid = Bid.fromJson(doc.data());
bid.bidId = doc.id;
bid.userName = await getDbUserNameFromDbUserID( dbUserID: bid.bidderID);
bids.add(bid);
} catch (e) {
throw Exception(e);
}
}
return bids;
});
} catch (e) {
throw Exception(e);
}
}
This worked for me
SOLUTION
Stream<List<Bid>> getAllBidsByItemId({required String itemID}) async* {
try {
yield* _firestoreDB
.collection('bids')
.where('itemID', isEqualTo: itemID)
.snapshots()
.asyncMap<List<Bid>>((event) async {
List<Bid> bids = [];
for (var doc in event.docs) {
try {
Bid bid = Bid.fromJson(doc.data());
bid.bidId = doc.id;
bid.userName = await getDbUserNameFromDbUserID( dbUserID: bid.bidderID);
bids.add(bid);
} catch (e) {
throw Exception(e);
}
}
return bids;
});
} catch (e) {
throw Exception(e);
}}

My DocumentSnapshot type variable remains null despite the fact that I passed it to my function

I use flutter to retrieve a document from my firestore database. to do this, I create a DocumentSnapshot type variable which will be passed as a parameter to my getClasseName() function to retrieve the documents. Inside my function the document exists, so I assign it to my variable but my variable remains null when I want to use it
this is a snippet of my code
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:ude/model/enseignant.dart';
class DBServices {
static final CollectionReference lyceecol =
FirebaseFirestore.instance.collection('Lycee');
static Future getUser(String? lycee, String? id) async {
try {
final QuerySnapshot<Object?> snapshot = await lyceecol
.doc(lycee)
.collection('Enseignant')
.where('Id', isEqualTo: id)
.get();
final EnseignantM userData = snapshot.docs
.map((QueryDocumentSnapshot<Object?> e) => EnseignantM.fromSnapshot(
e as DocumentSnapshot<Map<String?, dynamic>>))
.single;
return userData;
} catch (e) {
print('ENSEIGNANT NOT FOUND');
print(e);
throw e;
}
}
static Future getClasseName(
String? lycee, String? id, List<String> list) async {
try {
String classeName;
int i = 0;
final snapshot = await lyceecol
.doc(lycee)
.collection('Enseignant')
.doc(id)
.collection('Classes')
.get();
for (var classe in snapshot.docs) {
DocumentReference<Map<String, dynamic>> classeRef =
classe.data()["reference"];
DocumentSnapshot<Map<String, dynamic>>? classRoom;
await DBServices.getClasse(classeRef.path, classRoom);
if (classRoom != null) {
print('CLASSENAME ${classRoom.data()!["Nom"]}');
classeName = classRoom.data()!["Nom"];
list[i] = classeName;
print(list[i]);
i++;
} else {
print('Impossible de charger les classes affilees a cet enseignant');
}
}
} catch (e) {
print(e);
rethrow;
}
}
static Future<void> getClasse(
String? path, DocumentSnapshot<Map<String, dynamic>>? classroom) async {
try {
await FirebaseFirestore.instance.doc(path!).get().then((snapshot) {
if (snapshot.exists) {
classroom = snapshot; //.data()!["Nom"];
} else {
debugPrint("Document not found");
}
});
debugPrint('CLASSROOMMMM: ${classroom!.data()!["Nom"]}');
} catch (e) {
debugPrint('CLASSE Not EXIST');
print(e);
rethrow;
}
}
}
---
/*this is where the problem is*/
static Future getClasseName(
String? lycee, String? id, List<String> list) async {
try {
String classeName;
int i = 0;
final snapshot = await lyceecol
.doc(lycee)
.collection('Enseignant')
.doc(id)
.collection('Classes')
.get();
for (var classe in snapshot.docs) {
DocumentReference<Map<String, dynamic>> classeRef =
classe.data()["reference"];
DocumentSnapshot<Map<String, dynamic>>? classRoom;
await DBServices.getClasse(classeRef.path, classRoom);
if (classRoom != null) {
print('CLASSENAME ${classRoom.data()!["Nom"]}');
classeName = classRoom.data()!["Nom"];
list[i] = classeName;
print(list[i]);
i++;
} else {
print('Impossible de charger les classes affilees a cet enseignant');
}
}
} catch (e) {
print(e);
rethrow;
}
}
static Future<void> getClasse(
String? path, DocumentSnapshot<Map<String, dynamic>>? classroom) async {
try {
await FirebaseFirestore.instance.doc(path!).get().then((snapshot) {
if (snapshot.exists) {
classroom = snapshot; //.data()!["Nom"];
} else {
debugPrint("Document not found");
}
});
debugPrint('CLASSROOMMMM: ${classroom!.data()!["Nom"]}');
} catch (e) {
debugPrint('CLASSE Not EXIST');
print(e);
rethrow;
}
}
I tried not to pass my variable as a parameter and to directly assign the Document returned by the function to it, but it didn't work.
Your help will be invaluable to me

type 'Null' is not a subtype of type 'DatabaseNotes' in type cast

The problem lies in the FutureBuilder widget section. I am trying to get the data from a snapshot in a FutureBuilder, but I get an error as 'type 'Null' is not a subtype of type 'DatabaseNotes' in type cast'. I tried declaring the _note field as late final but it still throws the same error. I have taken care of the null safety part by adding the ? in after the data type (here, it is DatabaseNotes). I still don't get what is wrong here.
The following is the code for the NewNoteView widget:
class NewNoteView extends StatefulWidget {
const NewNoteView({Key? key}) : super(key: key);
#override
State<NewNoteView> createState() => _NewNoteViewState();
}
class _NewNoteViewState extends State<NewNoteView> {
DatabaseNotes? _note;
late final NotesService _notesService;
late final TextEditingController _textController;
#override
void initState() {
_notesService = NotesService();
_textController = TextEditingController();
super.initState();
}
void _textControllerListener() async {
final note = _note;
if (note == null) {
return;
}
final text = _textController.text;
await _notesService.updateNote(
note: note,
text: text,
);
}
void _setupTextControllerListener() {
_textController.removeListener(_textControllerListener);
_textController.addListener(_textControllerListener);
}
Future<DatabaseNotes> createNewNote() async {
final existingNote = _note;
if (existingNote != null) {
return existingNote;
}
final currentUser = AuthService.firebase().currentUser!;
final email = currentUser.email!;
final owner = await _notesService.getUser(email: email);
return await _notesService.createNote(owner: owner);
}
void _deleteNoteIfTextIsEmpty() {
final note = _note;
if (_textController.text.isEmpty && note != null) {
_notesService.deleteNote(id: note.id);
}
}
void _saveNoteIfTextNotEmpty() async {
final note = _note;
final text = _textController.text;
if (note != null && text.isNotEmpty) {
await _notesService.updateNote(
note: note,
text: text,
);
}
}
#override
void dispose() {
_deleteNoteIfTextIsEmpty();
_saveNoteIfTextNotEmpty();
_textController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('New note'),
),
body: FutureBuilder(
future: createNewNote(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.done:
_note = snapshot.data as DatabaseNotes;
_setupTextControllerListener();
return TextField(
controller: _textController,
keyboardType: TextInputType.multiline,
maxLines: null,
decoration: const InputDecoration(
hintText: 'Start typing your note...',
),
);
default:
return const CircularProgressIndicator();
}
},
));
}
}
The following is the code for NotesService:
class DatabaseAlreadyOpenException implements Exception {}
class NotesService {
Database? _db;
List<DatabaseNotes> _notes = [];
static final NotesService _shared = NotesService._sharedInstance();
NotesService._sharedInstance();
factory NotesService() => _shared;
final _notesStreamController =
StreamController<List<DatabaseNotes>>.broadcast();
Stream<List<DatabaseNotes>> get allNotes => _notesStreamController.stream;
Future<DatabaseUser> getOrCreateUser({required String email}) async {
try {
final user = getUser(email: email);
return user;
} on CouldNotFindUser {
final createdUser = createUser(email: email);
return createdUser;
} catch (e) {
rethrow;
}
}
Future<void> _cacheNotes() async {
final allNotes = await getAllNotes();
_notes = allNotes.toList();
_notesStreamController.add(_notes);
}
Future<DatabaseNotes> updateNote({
required DatabaseNotes note,
required String text,
}) async {
await _ensureDbIsOpen();
final db = _getDatabaseOrThrow();
// make sure note exists
await getNote(id: note.id);
// update DB
final updatesCount = await db.update(notesTable, {
textColumn: text,
isSyncedWithCloudColumn: 0,
});
if (updatesCount == 0) {
throw CouldNotUpdateNote();
} else {
final updatedNote = await getNote(id: note.id);
_notes.removeWhere((note) => note.id == updatedNote.id);
_notes.add(updatedNote);
_notesStreamController.add(_notes);
return updatedNote;
}
}
Future<Iterable<DatabaseNotes>> getAllNotes() async {
await _ensureDbIsOpen();
final db = _getDatabaseOrThrow();
final notes = await db.query(
notesTable,
);
return notes.map((noteRow) => DatabaseNotes.fromRow(noteRow));
}
Future<DatabaseNotes> getNote({required int id}) async {
await _ensureDbIsOpen();
final db = _getDatabaseOrThrow();
final notes = await db.query(
notesTable,
limit: 1,
where: 'id = ?',
whereArgs: [id],
);
if (notes.isEmpty) {
throw CouldNotFindNote();
} else {
final note = DatabaseNotes.fromRow(notes.first);
_notes.removeWhere((note) => note.id == id);
_notes.add(note);
_notesStreamController.add(_notes);
return note;
}
}
Future<int> deleteAllNotes() async {
await _ensureDbIsOpen();
final db = _getDatabaseOrThrow();
final numberOfDeletions = await db.delete(notesTable);
_notes = [];
_notesStreamController.add(_notes);
return numberOfDeletions;
}
Future<void> deleteNote({required int id}) async {
await _ensureDbIsOpen();
final db = _getDatabaseOrThrow();
final deletedCount = await db.delete(
notesTable,
where: 'id = ?',
whereArgs: [id],
);
if (deletedCount == 0) {
throw CouldNotDeleteNote();
} else {
_notes.removeWhere((note) => note.id == id);
_notesStreamController.add(_notes);
}
}
Future<DatabaseNotes> createNote({required DatabaseUser owner}) async {
await _ensureDbIsOpen();
final db = _getDatabaseOrThrow();
// make sure the owner exists in the database with the correct id
final dbUser = await getUser(email: owner.email);
if (dbUser != owner) {
throw CouldNotFindUser();
}
const text = '';
// create the note
final noteId = await db.insert(notesTable, {
userIdColumn: owner.id,
textColumn: text,
isSyncedWithCloudColumn: 1,
});
final note = DatabaseNotes(
id: noteId,
userId: owner.id,
text: text,
isSyncedWithCloud: true,
);
_notes.add(note);
_notesStreamController.add(_notes);
return note;
}
Future<DatabaseUser> getUser({required String email}) async {
await _ensureDbIsOpen();
final db = _getDatabaseOrThrow();
final results = await db.query(
userTable,
limit: 1,
where: 'email = ?',
whereArgs: [email.toLowerCase()],
);
if (results.isEmpty) {
throw CouldNotFindUser();
} else {
return DatabaseUser.fromRow(results.first);
}
}
Future<DatabaseUser> createUser({required String email}) async {
await _ensureDbIsOpen();
final db = _getDatabaseOrThrow();
final results = await db.query(
userTable,
limit: 1,
where: 'email = ?',
whereArgs: [email.toLowerCase()],
);
if (results.isNotEmpty) {
throw UserAlreadyExists();
}
final userId = await db.insert(userTable, {
emailColumn: email.toLowerCase(),
});
return DatabaseUser(
id: userId,
email: email,
);
}
Future<void> deleteUser({required String email}) async {
await _ensureDbIsOpen();
final db = _getDatabaseOrThrow();
final deletedCount = await db.delete(
userTable,
where: 'email = ?',
whereArgs: [email.toLowerCase()],
);
if (deletedCount != 1) {
throw CouldNotDeleteUser();
}
}
Database _getDatabaseOrThrow() {
final db = _db;
if (db == null) {
throw DatabaseIsNotOpen();
} else {
return db;
}
}
Future<void> close() async {
final db = _db;
if (db == null) {
throw DatabaseIsNotOpen();
} else {
await db.close();
_db = null;
}
}
Future<void> _ensureDbIsOpen() async {
try {
await open();
} on DatabaseAlreadyOpenException {
//empty block
}
}
Future<void> open() async {
if (_db != null) {
throw DatabaseAlreadyOpenException;
}
try {
final docsPath = await getApplicationDocumentsDirectory();
final dbPath = join(docsPath.path, dbName);
final db = await openDatabase(dbPath);
_db = db;
// create the user table
await db.execute(createUserTable);
// create the notes table
await db.execute(createNotesTable);
await _cacheNotes();
} on MissingPlatformDirectoryException {
throw UnableToGetDocumentsDirectory;
}
}
}
#immutable
class DatabaseUser {
final int id;
final String email;
const DatabaseUser({
required this.id,
required this.email,
});
DatabaseUser.fromRow(Map<String, Object?> map)
: id = map[idColumn] as int,
email = map[emailColumn] as String;
#override
String toString() => 'Person id = $id, email = $email';
#override
bool operator ==(covariant DatabaseUser other) => id == other.id;
#override
int get hashCode => id.hashCode;
}
class DatabaseNotes {
final int id;
final int userId;
final String text;
final bool isSyncedWithCloud;
DatabaseNotes({
required this.id,
required this.userId,
required this.text,
required this.isSyncedWithCloud,
});
DatabaseNotes.fromRow(Map<String, Object?> map)
: id = map[idColumn] as int,
userId = map[userIdColumn] as int,
text = map[textColumn] as String,
isSyncedWithCloud = (map[isSyncedWithCloudColumn]) == 1 ? true : false;
#override
String toString() =>
'Note, ID = $id, userId = $userId, isSyncedWithCloud = $isSyncedWithCloud, text = $text';
#override
bool operator ==(covariant DatabaseNotes other) => id == other.id;
#override
int get hashCode => id.hashCode;
}
You can place the '?' after DatabaseNotes (or DatabaseNote if you are following the FreeCodeCamp tutorial more precisely). Your IDE will probably then tell you the cast to DatabaseNotes is unnecessary. I then removed the 'as DatabaseNotes' entirely and it worked. Final line of code as below.
_note = snapshot.data;
Try this
FutureBuilder<DatabaseNotes>(your code);
I found the mistake and turns out I wasn't handling the null safety after all; I feel like an idiot.
I created an instance of 'DatabaseNotes?' _note, but when I assigned the snapshot's data inside the FutureBuilder in the line _note = snapshot.data as DatabaseNotes, I forgot to add the ? after DatabaseNotes.
The statement should be: _note = snapshot.data as DatabaseNotes?;
Thank you everyone for your answers and suggestions. I highly appreciate your efforts.
After
_note = snapshot.data as DatabaseNotes;
just put
?
This null safety sign. And your code will run errorless. My code so suffers for this damn sign.

" _CastError (Null check operator used on a null value) " Flutter

When interacting with my function that initiate specs, flutter return me this error : "_CastError (Null check operator used on a null value)"
error code :
initSpecsTechs() async {
specs = await APIBike()
.getSpecsTechs(jwt: _user!.jwt, bikeId: favoriteBike!.id);
initBluetoothConnection();
initSliderAutomaticExtinctionValue();
initSliderAutomaticLockingValue();
initBackLightMode();
}
Full code of my page setting (first line contain the error code):
import 'package:myapp/api_bike.dart';
import 'package:myapp/api_user.dart';
import 'package:myapp/ux_components.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'blur_filter.dart';
class SettingsPage extends StatefulWidget {
#override
SettingsPageState createState() => SettingsPageState();
SettingsPage({required Key key}) : super(key: key);
}
class SettingsPageState extends State<SettingsPage>
with AutomaticKeepAliveClientMixin<SettingsPage> {
User? _user;
List<Bike> _bikes = [];
Bike? favoriteBike;
Specs? specs;
bool connectedByBluetooth = true;
double _currentSliderAutomaticExtinctionValue = 0;
double _currentSliderAutomaticLockingValue = 0;
bool theftAlertIsActive = true;
bool batteryAlertIsActive = true;
bool maintainAlertIsActive = true;
bool constantBackLight = true;
double spaceAfterSmallTitle = 15;
double spaceAfterWidget = 20;
//INIT FUNCTIONS
init() async {
await initUser();
await initBikes();
await initFavoriteBike();
await initSpecsTechs();
}
Future initUser() async {
final storage = new FlutterSecureStorage();
String mail = await storage.read(key: "mail") ?? "";
String password = await storage.read(key: "password") ?? "";
UserResponse userResponse = await APIUser()
.login(mail, password); //L'identifiant peut être le username ou le mail
User? user = userResponse.user;
if (user != null) {
setState(() {
_user = user;
});
}
return user;
}
initBikes() async {
if (_user != null) {
List<Bike> bikes = await APIBike().getAllUserBikes(jwt: _user!.jwt);
setState(() {
_bikes = bikes;
});
} else {
print("could not get the bikes call the user is null");
}
}
initFavoriteBike() async {
if (_bikes.length == 0) {
favoriteBike = null;
} else if (_bikes.length == 1) {
setState(() {
favoriteBike = _bikes.first;
});
} else {
Bike? favBike = await APIBike().getFavoriteBike(jwt: _user!.jwt);
if (favBike != null) {
setState(() {
favoriteBike = favBike;
});
} else {
print("PROBLEM : FAVORITE BIKE IS NULL");
}
}
}
initSpecsTechs() async {
specs = await APIBike()
.getSpecsTechs(jwt: _user!.jwt, bikeId: favoriteBike!.id);
initBluetoothConnection();
initSliderAutomaticExtinctionValue();
initSliderAutomaticLockingValue();
initBackLightMode();
}
initBackLightMode() {
if (specs != null) {
bool constantBackLightValue = false;
if (specs!.rearLight == "fixed") {
constantBackLightValue = true;
}
setState(() {
constantBackLight = constantBackLightValue;
});
} else {
print("Fake value used for initBackLightMode");
}
}
initTheftAlertIsActive() {
if (specs != null) {
setState(() {
theftAlertIsActive = specs!.theftAlarm;
});
} else {
print("Fake value used for initStealAlertIsActive");
}
}
initBatteryAlertIsActive() {
if (specs != null) {
setState(() {
batteryAlertIsActive = specs!.batteryAlarm;
});
} else {
print("Fake value used for initBatteryAlertIsActive");
}
}
initMaintenanceAlertIsActive() {
if (specs != null) {
setState(() {
maintainAlertIsActive = specs!.maintenanceAlarm;
});
} else {
print("Fake value used for initMaintenanceAlertIsActive");
}
}
initBluetoothConnection() {
//If this value is false then the page is all grey with nothing active
setState(() {
connectedByBluetooth = true;
});
}
initSliderAutomaticExtinctionValue() {
if (specs != null) {
double sliderValue = 0;
if (specs!.automaticSwitchOff == 0) {
sliderValue = 4;
} else if (specs!.automaticSwitchOff == 5) {
sliderValue = 0;
} else if (specs!.automaticSwitchOff == 10) {
sliderValue = 1;
} else if (specs!.automaticSwitchOff == 15) {
sliderValue = 2;
} else if (specs!.automaticSwitchOff == 20) {
sliderValue = 3;
} else {
//If there is a problem (it is not suppose to happen, we set it to never)
sliderValue = 0;
}
setState(() {
_currentSliderAutomaticExtinctionValue = sliderValue;
});
} else {
print("Fake value used for initSliderAutomaticExtinctionValue");
}
}
initSliderAutomaticLockingValue() {
if (specs != null) {
double sliderValue = 0;
if (specs!.automaticLocking == 0) {
sliderValue = 4;
} else if (specs!.automaticLocking == 1) {
sliderValue = 0;
} else if (specs!.automaticLocking == 3) {
sliderValue = 1;
} else if (specs!.automaticLocking == 5) {
sliderValue = 2;
} else if (specs!.automaticLocking == 10) {
sliderValue = 3;
} else {
//If there is a problem (it is not suppose to happen, we set it to never)
sliderValue = 0;
}
setState(() {
_currentSliderAutomaticLockingValue = sliderValue;
});
} else {
print("Fake value used for initSliderAutomaticLockingValue");
}
}
#override
void initState() {
super.initState();
init();
}
//UPDATE FUNCTIONS
updateRearLightValue(String newValue) async {
//TODO change the value on the bike by BLE
bool operationSucceed = await APIBike().updateSpecsTechs(
jwt: _user!.jwt,
bikeId: favoriteBike!.id,
specToUpdate: "rear_light",
newSpecValue: newValue);
if (operationSucceed) {
print("Rear light value updated successfully");
} else {
print("Error: rear light value didn't update correctly");
}
return operationSucceed;
}
updateAutomaticShutDownValue(double sliderValue) async {
//TODO change the value on the bike by BLE
int newValue = 0; // is also the value for never
if (sliderValue == 0) {
newValue = 5;
} else if (sliderValue == 1) {
newValue = 10;
} else if (sliderValue == 2) {
newValue = 15;
} else if (sliderValue == 3) {
newValue = 20;
} //else the new value is 0 which is never
bool operationSucceed = await APIBike().updateSpecsTechs(
jwt: _user!.jwt,
bikeId: favoriteBike!.id,
specToUpdate: "automatic_switch_off",
newSpecValue: newValue);
if (operationSucceed) {
print("Automatic switch off value updated successfully");
} else {
print("Error: Automatic switch off value didn't update correctly");
}
return operationSucceed;
}
updateAutomaticLockingValue(double sliderValue) async {
//TODO change the value on the bike by BLE
int newValue = 0; // is also the value for never
if (sliderValue == 0) {
newValue = 1;
} else if (sliderValue == 1) {
newValue = 3;
} else if (sliderValue == 2) {
newValue = 5;
} else if (sliderValue == 3) {
newValue = 10;
} //else the new value is 0 which is never
bool operationSucceed = await APIBike().updateSpecsTechs(
jwt: _user!.jwt,
bikeId: favoriteBike!.id,
specToUpdate: "automatic_locking",
newSpecValue: newValue);
if (operationSucceed) {
print("Automatic locking value updated successfully");
} else {
print("Error: Automatic locking value didn't update correctly");
}
return operationSucceed;
}
updateTheftAlertIsActive(bool newValue) async {
bool operationSucceed = await APIBike().updateSpecsTechs(
jwt: _user!.jwt,
bikeId: favoriteBike!.id,
specToUpdate: "theft_alarm",
newSpecValue: newValue);
if (operationSucceed) {
print("Theft alert value updated successfully");
} else {
print("Error: theft alert value didn't update correctly");
}
return operationSucceed;
}
updateBatteryAlertIsActive(bool newValue) async {
bool operationSucceed = await APIBike().updateSpecsTechs(
jwt: _user!.jwt,
bikeId: favoriteBike!.id,
specToUpdate: "battery_alarm",
newSpecValue: newValue);
if (operationSucceed) {
print("Battery alert value updated successfully");
} else {
print("Error: battery alert value didn't update correctly");
}
return operationSucceed;
}
updateMaintenanceAlertIsActive(bool newValue) async {
bool operationSucceed = await APIBike().updateSpecsTechs(
jwt: _user!.jwt,
bikeId: favoriteBike!.id,
specToUpdate: "maintenance_alarm",
newSpecValue: newValue);
if (operationSucceed) {
print("Maintenance alert value updated successfully");
} else {
print("Error: maintenance alert value didn't update correctly");
}
return operationSucceed;
}
/.../
And finally my api for the user :
import 'dart:collection';
import 'package:myapp/api_bike.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
class ResponseWithError {
final bool result;
final String error;
ResponseWithError(this.result, this.error);
}
class APIUser {
//For dev
final String serverAddress =
"https://myadress.com/";
//TODO For production:
//final String serverAddress = "https://prodadress.com";
Future<ResponseWithError> createUser(
String firstname, String lastname, String email, String password) async {
var body =
"""{"username": "$firstname $lastname", "firstname": "$firstname", "lastname": "$lastname", "email": "$email", "password": "$password"}""";
var client = new http.Client();
var response = await client.post(
Uri.parse("$serverAddress/auth/local/register"),
body: body,
headers: {"Content-Type": 'application/json'});
if (response.statusCode == 200) {
print("USER CREATED");
print(response.body);
return ResponseWithError(true, "none");
} else {
print("Error " + response.statusCode.toString());
print("Response Body");
print(response.body);
var responseBody = jsonDecode(response.body);
if (responseBody["message"][0]["messages"][0]["id"] != null) {
String errorMessageId = responseBody["message"][0]["messages"][0]["id"];
if (errorMessageId == "Auth.form.error.email.format") {
return ResponseWithError(false, "email format");
}
}
return ResponseWithError(false, "not known");
}
}
Future<UserResponse> login(String identifier, String password) async {
var body = """{"identifier": "$identifier", "password": "$password"}""";
var client = new http.Client();
var response = await client.post(Uri.parse("$serverAddress/auth/local"),
body: body, headers: {"Content-Type": 'application/json'});
if (response.statusCode == 200) {
//print("USER LOGGED IN");
final parsed = jsonDecode(response.body);
User user = User.fromJson(parsed);
UserResponse userResponse = UserResponse(user, true);
return userResponse;
} else {
//print("Error " + response.statusCode.toString());
//print("Response Body");
//print(response.body);
var responseBody = jsonDecode(response.body);
if (responseBody["message"][0]["messages"][0]["id"] != null) {
String errorMessageId = responseBody["message"][0]["messages"][0]["id"];
if (errorMessageId == "Auth.form.error.confirmed") {
print("User not confirmed");
UserResponse userResponse = UserResponse(null, false);
return userResponse;
} else /*if(errorMessageId == "Auth.form.error.invalid")*/ {
print("email or password incorrect");
UserResponse userResponse = UserResponse(null, true);
return userResponse;
}
}
//Should not happen, but just in case
UserResponse userResponse = UserResponse(null, true);
return userResponse;
}
}
Future<bool> updateToken(String jwt, String notificationId) async {
var body = """{"notification_id": "$notificationId"}""";
var client = new http.Client();
var response = await client.put(Uri.parse("$serverAddress/users/token"),
body: body,
headers: {
"Content-Type": 'application/json',
'Authorization': 'Bearer $jwt'
});
if (response.statusCode == 200) {
print("NOTIFICATION TOKEN UPDATED");
return true;
} else {
print("Error " + response.statusCode.toString());
print("Response Body");
print(response.body);
return false;
}
}
Future<bool> updateEmail(String jwt, String newEmail) async {
var confirmed = false;
var body = """{"email": "$newEmail", "confirmed": "$confirmed"}""";
var client = new http.Client();
var response = await client.put(Uri.parse("$serverAddress/users/me"),
body: body,
headers: {
"Content-Type": 'application/json',
'Authorization': 'Bearer $jwt'
});
if (response.statusCode == 200) {
print("EMAIL UPDATED");
return true;
} else {
print("Error " + response.statusCode.toString());
print("Response Body");
print(response.body);
return false;
}
}
Future<bool> updateNames(
String jwt, String newFirstname, String newLastName) async {
var body =
"""{"username": "$newFirstname $newLastName", "firstname": "$newFirstname", "lastname": "$newLastName"}""";
var client = new http.Client();
var response = await client.put(Uri.parse("$serverAddress/users/me"),
body: body,
headers: {
"Content-Type": 'application/json',
'Authorization': 'Bearer $jwt'
});
if (response.statusCode == 200) {
print("NAMES UPDATED");
return true;
} else {
print("Error " + response.statusCode.toString());
print("Response Body");
print(response.body);
return false;
}
}
Future<bool> updatePassword(String jwt, String newPassword) async {
var body = """{"password": "$newPassword"}""";
var client = new http.Client();
var response = await client.put(Uri.parse("$serverAddress/users/me"),
body: body,
headers: {
"Content-Type": 'application/json',
'Authorization': 'Bearer $jwt'
});
if (response.statusCode == 200) {
print("PASSWORD UPDATED");
return true;
} else {
print("Error " + response.statusCode.toString());
print("Response Body");
print(response.body);
return false;
}
}
Future<bool> sendConfirmationCode(String email) async {
var body = """{"email": "$email"}""";
var client = new http.Client();
var response = await client.post(
Uri.parse("$serverAddress/auth/send-email-confirmation"),
body: body,
headers: {"Content-Type": 'application/json'});
if (response.statusCode == 200) {
print("EMAIL SENT to $email");
return true;
} else {
print("Error " + response.statusCode.toString());
print("Response Body");
print(response.body);
return false;
}
}
Future<bool> verifyEmail(String email, String code) async {
var body = """{"email": "$email", "confirmation": "$code"}""";
var client = new http.Client();
var response = await client.put(
Uri.parse("$serverAddress/auth/email-confirmation"),
body: body,
headers: {"Content-Type": 'application/json'});
if (response.statusCode == 200) {
print("EMAIL VERIFIED");
return true;
} else {
print("Error " + response.statusCode.toString());
print("Response Body");
print(response.body);
return false;
}
}
Future<bool> passwordForgotten({required String email}) async {
var body = """{"email": "$email"}""";
var client = new http.Client();
var response = await client.post(
Uri.parse("$serverAddress/auth/forgot-password"),
body: body,
headers: {"Content-Type": 'application/json'});
if (response.statusCode == 200) {
return true;
} else {
print("Error passwordForgotten :" + response.statusCode.toString());
print("Response Body");
print(response.body);
return false;
}
}
}
class UserResponse {
User? user;
bool userConfirmed;
UserResponse(this.user, this.userConfirmed);
}
class User {
final int id;
final String jwt;
final String username;
final String firstname;
final String lastname;
final String email;
final String provider;
final bool confirmed;
final bool? blocked;
final String? notificationId;
final String createdAt;
final String updatedAt;
final List<int>?
bikesId; //Here we just save the ids of the bikes linked to the user
final Subscription? subscription;
final Role role;
User({
required this.id,
required this.jwt,
required this.username,
required this.firstname,
required this.lastname,
required this.email,
required this.provider,
required this.confirmed,
required this.blocked,
required this.notificationId,
required this.createdAt,
required this.updatedAt,
required this.bikesId,
required this.subscription,
required this.role,
});
factory User.fromJson(Map<String, dynamic> json) {
if (json['user']['subscription'] != null) {
return User(
id: json['user']['id'] as int,
jwt: json['jwt'] as String,
username: json['user']['username'] as String,
firstname: json['user']['firstname'] as String,
lastname: json['user']['lastname'] as String,
email: json['user']['email'] as String,
provider: json['user']['provider'] as String,
confirmed: json['user']['confirmed'] as bool,
blocked: json['user']['blocked'] as bool?,
notificationId: json['user']['notification_id'] as String?,
createdAt: json['user']['created_at'] as String,
updatedAt: json['user']['updated_at'] as String,
bikesId: createBikesIdList(json['user']['bikes_id']),
subscription: Subscription(
id: json['user']['subscription']['id'],
name: json['user']['subscription']['name'],
createdAt: json['user']['subscription']['created_at'],
updatedAt: json['user']['subscription']['updated_at']),
role: Role(
id: json['user']['role']['id'],
name: json['user']['role']['name'],
description: json['user']['role']['description'],
type: json['user']['role']['type'],
));
} else {
return User(
id: json['user']['id'] as int,
jwt: json['jwt'] as String,
username: json['user']['username'] as String,
firstname: json['user']['firstname'] as String,
lastname: json['user']['lastname'] as String,
email: json['user']['email'] as String,
provider: json['user']['provider'] as String,
confirmed: json['user']['confirmed'] as bool,
blocked: json['user']['blocked'] as bool?,
notificationId: json['user']['notification_id'] as String?,
createdAt: json['user']['created_at'] as String,
updatedAt: json['user']['updated_at'] as String,
bikesId: createBikesIdList(json['user']['bikes_id']),
subscription: null,
role: Role(
id: json['user']['role']['id'],
name: json['user']['role']['name'],
description: json['user']['role']['description'],
type: json['user']['role']['type'],
));
}
}
describe() {
print("id : $id\njwt : $jwt");
}
}
class Role {
final int id;
final String name;
final String description;
final String type;
Role({
required this.id,
required this.name,
required this.description,
required this.type,
});
}
class Subscription {
final int id;
final String name;
final String createdAt;
final String updatedAt;
Subscription(
{required this.id,
required this.name,
required this.createdAt,
required this.updatedAt});
}
Can you try like this? I think user or favoriteBike is null. You need to null check.
initSpecsTechs() async {
if(_user != null && favoriteBike != null){
specs = await APIBike()
.getSpecsTechs(jwt: _user!.jwt, bikeId: favoriteBike!.id);
initBluetoothConnection();
initSliderAutomaticExtinctionValue();
initSliderAutomaticLockingValue();
initBackLightMode();
}
}
initSpecsTechs() async {
specs = await APIBike()
.getSpecsTechs(jwt: _user!.jwt, bikeId: favoriteBike!.id);
initBluetoothConnection();
initSliderAutomaticExtinctionValue();
initSliderAutomaticLockingValue();
initBackLightMode();
}
The "!" operator causes the exception instead use "?" like this
specs = await APIBike()
.getSpecsTechs(jwt: _user?.jwt??'', bikeId: favoriteBike?.id??'');

Flutter & Firebase - Get a specific field from document

I have been trying to get a specific field from a specific document. I need token for toWho. But I always got null. How do I fix this?
Main Code is
Future<String> getUserToken(String toWho) async {
DocumentSnapshot _doc = await FirebaseFirestore.instance.doc("tokens/" + toWho).get();
if (_doc != null) {
Map<String, dynamic> _data = _doc.data();
return _data["token"];
} else {
return null;
}
}
in Repository
Future<bool> sendMessage(
MessageModel sendingMessage, UserModel currentUser) async {
if (appMode == AppMode.DEBUG) {
return true;
} else {
var _writePrcs = await _firestoreDBService.saveMessage(sendingMessage);
if (_writePrcs) {
var _token = "";
if (_userToken.containsKey(sendingMessage.toWho)) {
_token = _userToken[sendingMessage.toWho];
print("Token lokalden geldi.");
} else {
_token = await _firestoreDBService.getUserToken(sendingMessage.toWho);
_userToken[sendingMessage.toWho] = _token;
print("Token veritabanından geldi.");
}
Thanks for your help from now on
Try ...........
Future<String> getUserToken(String toWho) async {
DocumentSnapshot _doc = await
FirebaseFirestore.instance.collection("tokens/groupChatId/message").doc(toWho).get();
if (_doc != null) {
Map<String, dynamic> _data = _doc.data();
return _data["token"];
} else {
return null;
}
}