I have an issue in my builder causing the following error juste after the builder in my match_page.dart :
"The body might complete normally, causing ‘null’ to be returned, but the return type, ‘Widget’, is a potentially non-nullable type.
Try adding either a return or a throw statement at the end."
The code in the main page:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:love_app/components/models/user.dart';
import 'package:love_app/components/repository/userRepository.dart';
import 'package:love_app/controllers/profile_controller.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:get/get.dart';
class MainPage extends StatelessWidget {
const MainPage({super.key});
void signUserOut(){
FirebaseAuth.instance.signOut();
}
@override
Widget build(BuildContext context) {
final controller = Get.put(ProfileController());
return Scaffold(
body: SingleChildScrollView(
child: FutureBuilder<List<UserModel>>(
future: controller.getAllUser(),
builder: (context, snapshot) {
if(snapshot.connectionState == ConnectionState.done){
if(snapshot.hasData){
// UserModel userData = snapshot.data as UserModel;
return GridView.count(
crossAxisCount: 2,
children: List.generate(snapshot.data!.length, (index) {
return Center(
child: Column(
children: [
Center(
child: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.04),
borderRadius: const BorderRadius.all(Radius.circular(16)),
),
height: 185,
width: 185,
margin:EdgeInsets.all(5.0)
),
),
Stack(
children: [
ListTile(
iconColor: Colors.blue,
tileColor: Colors.blue.withOpacity(0.1),
title: Text("Pseudo: ${snapshot.data![index].pseudo}"),
subtitle: Column(crossAxisAlignment: CrossAxisAlignment.start,
children: [Text("Nom: ${snapshot.data![index].nom}"),
Text("Prénom: ${snapshot.data![index].prenom}"),
Text("Description: ${snapshot.data![index].description}"),
Text("Passions: ${snapshot.data![index].passions}")
]
)
) ],
)
],),
);
}
),
);
}
else if (snapshot.hasError) {
print("Snapshot data: ${snapshot.data}");
return const SizedBox(
width: 200.0,
height: 300.0,
child: Card(child: Text('Passe dans else du erreur!')),
);}
else {
print("Snapshot data: ${snapshot.data}");
return const SizedBox(
width: 200.0,
height: 300.0,
child: Card(child: Text('Passe dans else du has data!')));}}})));}}
To find the informations from the user which are in my collection "Utilisateur" from Firestore I use the userRepository.dart :
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:love_app/components/models/user.dart';
class UserRepository extends GetxController {
static UserRepository get instance => Get.find();
final _db = FirebaseFirestore.instance;
Future<UserModel> getUserDetails(String id) async {
final snapshot = await _db.collection("Utilisateur").where("id", isEqualTo: id).get();
final userData = snapshot.docs.map((e) => UserModel.fromSnapshot(e)).single;
return userData;
}
Future<List<UserModel>> allUser() async {
final snapshot = await _db.collection("Utilisateur").get();
final userData = snapshot.docs.map((e) => UserModel.fromSnapshot(e)).toList();
return userData;
}
}
And I Use also this profile_controller.dart:
import 'package:get/get.dart';
import 'package:love_app/components/repository/userRepository.dart';
import 'package:love_app/components/models/user.dart';
class ProfileController extends GetxController {
static ProfileController get instance => Get.find();
final _userRepo = Get.put(UserRepository());
Future<UserModel> getUserData() {
const id = "9uVSkDP4Twqh0FWCekXV";
// TODo: essayer de récupérer l'id du user connecté
return _userRepo.getUserDetails(id);
}
Future<List<UserModel>> getAllUser() async {
return await _userRepo.allUser();
}
}
My user.dart:
import 'package:cloud_firestore/cloud_firestore.dart';
class UserModel {
final String id;
final String description;
final String nom;
final String passions;
final String prenom;
final String pseudo;
const UserModel({
required this.id,
required this.description,
required this.nom,
required this.passions,
required this.prenom,
required this.pseudo,
toJson() {
return { "Description" : description, "Nom": nom, "Passions": passions,
"Prenom": prenom , "Pseudo": pseudo};
}
factory UserModel.fromSnapshot(DocumentSnapshot<Map<String, dynamic>> document) {
final data = document.data()!;
return UserModel (
id: document.id,
description: data['Description'],
nom: data['Nom'],
passions: data['Passions'],
prenom: data['Prenom'],
pseudo: data['Pseudo'],
);
}
}
All of these functions has a return so I can’t identify where is the problem.
Could you please help me to resolve it?
3
Answers
The else if and else conditions are at the end of the code like this:
These conditions are supplying all the conditions, no? If the snapshot has a data, else if there is an error or else if any other conditions are met.
I guess it happens because of your first if in your builder.
You only return a widget if your
if(snapshot.connectionState == ConnectionState.done)
condition is true. But if not, you do nothing. Return a widget if the connection state is not done.
As Ozan answered, your
builder
method only returns a widget when the data has successfully loaded, but it always needs to return a widget – even when those conditions have not been met.My common way of implementing
builder
: