How to Display Progress Wheel/Bar between Flutter transitions? - flutter

I've created a custom Login Page that looks and works the way I intended. I'm having trouble figuring out how and where in my code to display a progress indicator while it authenticates the Firebase User and pulls the users name, photo, or placeholders. Also, if authentication fails, where and how should an alert be displayed. Here is my current code...
Future<Null> _loginButton() async {
_email = _emailController.text.toString().replaceAll(" ", "");
_password = _passController.text.toString().replaceAll(" ", "");
//_username = _nameController.text.toString().replaceAll(" ", "");
if (_email != null && _password != null) {
try {
await FirebaseAuth.instance
.signInWithEmailAndPassword(email: _email, password: _password);
final FirebaseUser currentUser = await _auth.currentUser();
final userid = currentUser.uid;
currentUserId = userid;
FirebaseDatabase.instance
.reference()
.child('users/$userid')
.onValue
.listen((Event event) {
if (event.snapshot.value == null) {
imageString = "placeholder";
name = _username;
} else if (event.snapshot.value != null) {
imageString = event.snapshot.value['image'];
name = event.snapshot.value['displayName'];
}
fb.child('users/$userid').set({
'displayName': name,
'image': imageString,
'uid' : userid.toString()
});
}).onDone(() {
Navigator.pushNamed(context, '/menu');
Main.uid = userid;
});
} catch (error) {
}
} else {}
}

Check this a functional example from my project to implement CircularProgressIndicator between flutter transitions.
class LoginPage extends StatefulWidget {
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
bool isLoading = false;
#override
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: isLoading
? Column(
children: <Widget>[
CircularProgressIndicator(),
Divider(
height: 20,
color: Colors.transparent,
),
Text("Please wait..."),
],
mainAxisSize: MainAxisSize.min,
)
: MaterialButton(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Image.asset(
'assets/google.png',
width: 25.0,
),
Padding(
child: Text(
"Sign in with Google",
style: TextStyle(
fontFamily: 'Roboto',
color: Color.fromRGBO(68, 68, 76, .8),
),
),
padding: new EdgeInsets.only(left: 15.0),
),
],
),
onPressed: () {
googleUserSignIn().then((user) {
this.setState(() {
//isLoading = false;
// Your task....
});
});
},
color: Colors.white,
elevation: 5,
highlightElevation: 2,
)));
}
Future<FirebaseUser> googleUserSignIn() async {
this.setState(() {
isLoading = true;
});
GoogleSignInAccount googleUser = await Firebase().firebaseGSI.signIn();
GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
FirebaseUser user =
await Firebase().firebaseAuth.signInWithCredential(credential);
return user;
}
}

Related

Exception caught by gesture. Null check operator used on a null value

here is the error message from the console
user.dart
import 'package:cloud_firestore/cloud_firestore.dart';
class User {
final String email;
final String uid;
final String photoUrl;
final String username;
final String bio;
final List<String> followers;
final List<String> following;
const User({
required this.email,
required this.uid,
required this.photoUrl,
required this.username,
required this.bio,
required this.followers,
required this.following,
});
static User fromSnap(DocumentSnapshot snap) {
var snapshot = snap.data() as Map<String, dynamic>;
return User(
username: snapshot["username"],
uid: snapshot["uid"],
email: snapshot["email"],
photoUrl: snapshot["photoUrl"],
bio: snapshot["bio"],
followers: snapshot["followers"],
following: snapshot["following"],
);
}
Map<String, dynamic> toJson() => {
"username": username,
"uid": uid,
"email": email,
"photoUrl": photoUrl,
"bio": bio,
"followers": followers,
"following": following,
};
}
user_provider
import 'package:flutter/material.dart';
import 'package:social_network/models/user.dart';
import 'package:social_network/resources/auth_method.dart';
class UserProvider with ChangeNotifier {
User? _user;
final AuthMethods _authMethods = AuthMethods();
User get getUser => _user!;
Future<void> refreshUser() async {
User? user = await _authMethods.getUserDetails();
_user = user;
notifyListeners();
}
}
add_post_screen
import 'dart:typed_data';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:provider/provider.dart';
import 'package:social_network/providers/user_provider.dart';
import 'package:social_network/resources/firestore_methods.dart';
import 'package:social_network/utils/colors.dart';
import 'package:social_network/utils/utils.dart';
class AddPostScreen extends StatefulWidget {
const AddPostScreen({Key? key}) : super(key: key);
#override
_AddPostScreenState createState() => _AddPostScreenState();
}
class _AddPostScreenState extends State<AddPostScreen> {
Uint8List? _file;
bool _isLoading = false;
final TextEditingController _descriptionController = TextEditingController();
_selectImage(BuildContext parentContext) async {
return showDialog(
context: parentContext,
builder: (BuildContext context) {
return SimpleDialog(
title: const Text('Create a post'),
children: <Widget>[
SimpleDialogOption(
padding: const EdgeInsets.all(20),
child: const Text('Take a photo'),
onPressed: () async {
Navigator.of(context).pop();
Uint8List file = await pickImage(ImageSource.camera);
setState(() {
_file = file;
});
},
),
SimpleDialogOption(
padding: const EdgeInsets.all(20),
child: const Text('Choose from gallery'),
onPressed: () async {
Navigator.of(context).pop();
Uint8List file = await pickImage(ImageSource.gallery);
setState(() {
_file = file;
});
},
),
SimpleDialogOption(
padding: const EdgeInsets.all(20),
child: const Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
});
}
void postImage(
String uid,
String username,
String profileImage,
) async {
setState(() {
_isLoading = true;
});
try {
String res = await FirestoreMethods().uploadPost(
_descriptionController.text, _file!, uid, username, profileImage);
if (res == "Succes") {
setState(() {
_isLoading = false;
});
showSnackBar('Posted!', context);
clearImage();
} else {
showSnackBar(res, context);
}
} catch (e) {
setState(() {
_isLoading = false;
});
showSnackBar(e.toString(), context);
}
}
void clearImage() {
setState(() {
_file = null;
});
}
#override
void dispose() {
super.dispose();
_descriptionController.dispose();
}
#override
Widget build(BuildContext context) {
final UserProvider userProvider = Provider.of<UserProvider>(context);
return _file == null
? Center(
child: IconButton(
icon: const Icon(Icons.upload),
onPressed: () => _selectImage(context),
),
)
: Scaffold(
appBar: AppBar(
backgroundColor: mobileBackgroundColor,
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: clearImage,
),
title: const Text('Post to'),
centerTitle: false,
actions: <Widget>[
TextButton(
onPressed: () => postImage(
userProvider.getUser.uid,
userProvider.getUser.username,
userProvider.getUser.photoUrl,
),
child: const Text(
'Post',
style: TextStyle(
color: Colors.redAccent,
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
),
],
),
body: Column(
children: [
_isLoading
? const LinearProgressIndicator()
: const Padding(
padding: EdgeInsets.only(top: 0),
),
const Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CircleAvatar(
backgroundImage: NetworkImage(
'https://images.unsplash.com/photo-1522441815192-d9f04eb0615c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=654&q=80',
// userProvider.getUser.photoUrl,
),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.4,
child: TextField(
controller: _descriptionController,
decoration: const InputDecoration(
hintText: 'Write a caption...',
border: InputBorder.none,
),
maxLines: 8,
),
),
SizedBox(
height: 45,
width: 45,
child: AspectRatio(
aspectRatio: 487 / 451,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: MemoryImage(_file!),
fit: BoxFit.fill,
alignment: FractionalOffset.topCenter,
),
),
),
),
),
const Divider(),
],
)
],
));
}
}
auth_methods.dart
import 'dart:typed_data';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:social_network/models/user.dart' as model;
import 'package:social_network/resources/storage_methods.dart';
class AuthMethods {
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
Future<model.User?> getUserDetails() async {
User currentUser = _auth.currentUser!;
DocumentSnapshot documentSnapshot =
await _firestore.collection('user').doc(currentUser.uid).get();
return model.User.fromSnap(documentSnapshot);
}
//sign up the user
Future<String> signUpUser({
required String email,
required String password,
required String username,
required String bio,
required Uint8List? file,
}) async {
String res = "Some error occurred";
try {
if (email.isNotEmpty ||
password.isNotEmpty ||
username.isNotEmpty ||
bio.isNotEmpty ||
file != null) {
//register the user
UserCredential cred = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
String photoUrl = await StorageMethods()
.uploadImageToStorage('profilePictures', file!, false);
//adding user to our database
model.User _user = model.User(
bio: bio,
username: username,
uid: cred.user!.uid,
email: email,
photoUrl: photoUrl,
following: [],
followers: [],
);
await _firestore.collection("users").doc(cred.user!.uid).set(
_user.toJson(),
);
res = "Succes";
} else {
res = "Please enter all the fields";
}
} catch (err) {
res = err.toString();
}
return res;
}
// logging the user
Future<String> loginUser(
{required String email, required String password}) async {
String res = "Some error occured";
try {
if (email.isNotEmpty || password.isNotEmpty) {
await _auth.signInWithEmailAndPassword(
email: email, password: password);
res = "Succes";
} else {
res = "Please enter all the fields required";
}
} catch (err) {
res = err.toString();
}
return res;
}
}
Hello. I'll try to make a post button and when I try to upload a photo and press the post button I receive this error.
Do you have any solution for this error? Thanks a lot!
Error message:
Restarted application in 474ms.
[VERBOSE-2:ui_dart_state.cc(198)] Unhandled Exception: type 'Null' is not a subtype of type 'Map<String, dynamic>' in type cast
════════ Exception caught by gesture ═══════════════════════════════════════════
Null check operator used on a null value
════════════════════════════════════════════════════════════════════════════════
[VERBOSE-2:profiler_metrics_ios.mm(203)] Error retrieving thread information: (os/kern) object terminated
I believe that your issue in
onPressed: () => postImage(
userProvider.getUser.uid,
userProvider.getUser.username,
userProvider.getUser.photoUrl,
),
Make sure that the user is not null before calling the method,
It would be more helpful to post more code _authMethods.getUserDetails(); what’s inside this method?
UPDATE:
Future<model.User?> getUserDetails() async {
User currentUser = _auth.currentUser!;
DocumentSnapshot documentSnapshot =
await _firestore.collection('user').doc(currentUser.uid).get();
//add the following lines
print('documentSnapshot: $documentSnapshot');
if(documentSnapshot == null) return null;
return model.User.fromSnap(documentSnapshot);
}

Null check operator used on null value flutter.dart

The logic in the program I wrote is that it is like Twitter. There will be photo sharing and text sharing. However, there is an error in my codes and when I do not share photos, I get the error 'Null check-operator used on null value'. How can I change this?
When I do not share photos, I get the error below.
These are my codes. I would appreciate it if you could tell me the changes I need to make.
add_post_screenn
class AddPostScreen extends StatefulWidget {
const AddPostScreen({Key? key}) : super(key: key);
#override
State<AddPostScreen> createState() => _AddPostScreenState();
}
class _AddPostScreenState extends State<AddPostScreen> {
Uint8List? _file;
final TextEditingController _descriptionController = TextEditingController();
bool _isLoading = false;
void postImage(
String uid,
String username,
String profImage,
) async {
setState(() {
_isLoading = true;
});
try {
String res = await FirestoreMethods().uploadPost(
_descriptionController.text, _file!, uid, username, profImage);
if (res == 'succes') {
setState(() {
_isLoading = false;
});
showSnackBar('Posted!', context);
clearImage();
} else {
showSnackBar(res, context);
}
} catch (e) {
showSnackBar(e.toString(), context);
}
}
_selectImage(BuildContext context) async {
return showDialog(
context: context,
builder: (context) {
return SimpleDialog(
title: const Text('Create a Post'),
children: [
SimpleDialogOption(
padding: const EdgeInsets.all(20),
child: const Text('Take a photo'),
onPressed: () async {
Navigator.of(context).pop();
Uint8List file = await pickImage(
ImageSource.camera,
);
setState(() {
_file = file;
});
},
),
SimpleDialogOption(
padding: const EdgeInsets.all(20),
child: const Text('Chose from gallery'),
onPressed: () async {
Navigator.of(context).pop();
Uint8List file = await pickImage(
ImageSource.gallery,
);
setState(() {
_file = file;
});
},
),
SimpleDialogOption(
padding: const EdgeInsets.all(20),
child: const Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
}),
],
);
});
}
void clearImage() {
_file = null;
}
#override
void dispose() {
super.dispose();
_descriptionController.dispose();
}
#override
Widget build(BuildContext context) {
final User user = Provider.of<UserProvider>(context).getUser;
//yorum satırı olacak
return _file == null
? Center(
child: IconButton(
icon: const Icon(Icons.upload),
onPressed: () => _selectImage(context),
),
)
// //buraya kadar
: Scaffold(
appBar: AppBar(
backgroundColor: mobileBackgroundColor,
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: clearImage,
),
title: const Text('Paylaşım'),
centerTitle: false,
actions: [
TextButton(
onPressed: () => postImage(
user.uid,
user.username,
user.photoUrl,
),
child: const Text(
'Paylaş',
style: TextStyle(
color: Colors.blueAccent,
fontWeight: FontWeight.bold,
fontSize: 16,
),
))
],
),
body: Column(
children: [
_isLoading
? const LinearProgressIndicator()
: const Padding(
padding: EdgeInsets.only(
top: 0,
),
),
const Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CircleAvatar(
backgroundImage: NetworkImage(user.photoUrl),
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.45,
child: TextField(
controller: _descriptionController,
decoration: const InputDecoration(
hintText: 'Hayallerini Yaz!',
border: InputBorder.none,
),
maxLines: 8,
),
),
SizedBox(
height: 45,
width: 45,
child: AspectRatio(
aspectRatio: 487 / 451,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: MemoryImage(_file!),
fit: BoxFit.fill,
alignment: FractionalOffset.topCenter,
)),
),
),
),
const Divider(),
],
),
],
),
);
}
}
firestore_methods
class FirestoreMethods {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
//upload post
Future<String> uploadPost(
String description,
Uint8List file,
String uid,
String username,
String profImage,
) async {
String res = 'Some error occurred';
try {
String photoUrl =
await StorageMethods().uploadImageToStorage('posts', file, true);
String postId = const Uuid().v1();
Post post = Post(
description: description,
uid: uid,
username: username,
postId: postId,
datePublished: DateTime.now(),
postUrl: photoUrl,
porfImage: profImage,
likes: [],
);
_firestore.collection('posts').doc(postId).set(
post.toJson(),
);
res = 'succes';
} catch (err) {
res = err.toString();
}
return res;
}
Future<void> LikePost(String postId, String uid, List likes) async {
try {
if (likes.contains(uid)) {
await _firestore.collection('posts').doc(postId).update({
'likes': FieldValue.arrayRemove([uid]),
});
} else {
await _firestore.collection('posts').doc(postId).update({
'likes': FieldValue.arrayUnion([uid]),
});
}
} catch (e) {
print(
e.toString(),
);
}
}
Future<void> postComment(String postId, String text, String uid, String name,
String profilePic) async {
try {
if (text.isNotEmpty) {
String commentId = const Uuid().v1();
await _firestore
.collection('posts')
.doc(postId)
.collection('comments')
.doc(commentId)
.set({
'profilePic': profilePic,
'name': name,
'uid': uid,
'text': text,
'commentId': commentId,
'datePublished': DateTime.now(),
});
} else {
print('Text is empty');
}
} catch (e) {
print(
e.toString(),
);
}
}
storage.methods
class StorageMethods {
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseStorage _storage = FirebaseStorage.instance;
// firebase deposuna resim ekleme firebase deposuna resim ekleme
Future<String> uploadImageToStorage(
String childName, Uint8List file, bool isPost) async {
// firebase depolama alanımıza konum oluşturma
Reference ref =
_storage.ref().child(childName).child(_auth.currentUser!.uid);
if (isPost) {
String id = const Uuid().v1();
ref = ref.child(id);
}
// putting in uint8list format -> Upload task like a future but not future
UploadTask uploadTask = ref.putData(file);
TaskSnapshot snap = await uploadTask;
String downloadUrl = await snap.ref.getDownloadURL();
return downloadUrl;
}
}
The error cause comes from the _file!. When posting only text there is going to be no _file as it's going to be null.
To fix this change the references from _file! to just _file and the FirestoreMethods.uploadPost should be the following:
FirestoreMethods.uploadPost - Change file to be nullable and check for null.
Future<String> uploadPost(
String description,
Uint8List? file, // <- Here
String uid,
String username,
String profImage,
) async {
String res = 'Some error occurred';
try {
String photoUrl = file != null // <- Here
? await StorageMethods().uploadImageToStorage('posts', file, true)
: '';
String postId = const Uuid().v1();
Post post = Post(
description: description,
uid: uid,
username: username,
postId: postId,
datePublished: DateTime.now(),
postUrl: photoUrl,
porfImage: profImage,
likes: [],
);
_firestore.collection('posts').doc(postId).set(
post.toJson(),
);
res = 'succes';
} catch (err) {
res = err.toString();
}
return res;
}
_AddPostScreenState.postImage - Change _file! to just _file
void postImage(
String uid,
String username,
String profImage,
) async {
setState(() {
_isLoading = true;
});
try {
String res = await FirestoreMethods().uploadPost(
_descriptionController.text, _file, uid, username, profImage);
if (res == 'succes') {
setState(() {
_isLoading = false;
});
showSnackBar('Posted!', context);
clearImage();
} else {
showSnackBar(res, context);
}
} catch (e) {
showSnackBar(e.toString(), context);
}
}
I think you are getting error in this line
Reference ref =
_storage.ref().child(childName).child(_auth.currentUser!.uid);
Here the current user maybe null. To fix this error for now you can use
Reference ref =
_storage.ref().child(childName).child(_auth.currentUser?.uid);
//Note instead of using ! I have used ? which means currentUser can be null. ! means you are marking that its not null and value is unknown
but please note that you are receiving _auth.currentUser as null. Please check those codes

How to make search FLUTTER JSON

I'm a new Flutter user, here I'm having a problem, I'm confused about how to make a search that reads from JSON, here I've created a search menu but I don't understand how to connect to the database. Can you help me to modify my source code so I can do a search. Hopefully good friends can help me make a search function. Thank you friend
datanasabah.dart
GlobalKey<ScaffoldState> _scaffoldState = GlobalKey<ScaffoldState>();
class DataNasabah extends StatefulWidget {
DataNasabah({Key key}) : super(key: key);
final String title = "Data Nasabah";
#override
_DataNasabahState createState() => _DataNasabahState();
}
class _DataNasabahState extends State<DataNasabah> {
ApiService apiService;
ListNasabah _listNasabah;
bool _isLoading = true;
List<Nasabah> data;
final _textHeadStyle =
TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold);
void fetchData() async {
final res = await apiService.getNasabah();
data = res;
setState(() {
_isLoading = false;
});
}
#override
void initState() {
super.initState();
apiService = ApiService();
_listNasabah = new ListNasabah(apiService: apiService);
fetchData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldState,
appBar: AppBar(
title: Text(
'Data Nasabah',
style: TextStyle(color: Colors.white),
),
actions: <Widget>[
MaterialButton(
elevation: 5,
child: Text("CARI", style: _textHeadStyle),
onPressed: () async {
var value = await showTopModalSheet<String>(
context: context, child: DumyModal());
},
),
],
),
body: _listNasabah.createViewList(),
);
}
}
class DumyModal extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
height: MediaQuery.of(context).size.height * .2,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
TextField(
decoration: InputDecoration(
labelText: "NIK Nasabah", //babel text
hintText: "Masukkan NIK Nasabah", //hint text
prefixIcon: Icon(Icons.people), //prefix iocn
hintStyle: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, ), //hint text style
labelStyle: TextStyle(fontSize: 17, color: Colors.black), //label style
)
),
MaterialButton(
color: Colors.orange,
child: const Text("Cari", style: TextStyle(color: Colors.white),),
onPressed: () {
FocusScope.of(context).requestFocus(FocusNode());
},
)
],
),
);
}
}
nasabah_service.dart
class ApiService {
final String baseUrl = '192.168.100.207:8080';
Client client = Client();
Future<List<Nasabah>> getNasabah() async {
final response = await client.get('http://$baseUrl/api/mstdebitur');
print(response.body);
if (response.statusCode == 200) {
final nasabah = (json.decode(response.body) as List)
.map((e) => Nasabah.fromMap(e))
.toList();
return nasabah;
} else {
throw Exception('Failed to load post');
}
}
Future<bool> createNasabah(Nasabah data) async {
String url = new Uri.http("$baseUrl", "/api/mstdebitur/").toString();
final response = await client.post(url,
headers: {"Content-Type": "application/json"},
body: nasabahToJson(data));
if (response.statusCode == 201) {
return true;
} else {
return false;
}
}
Future<bool> updateNasabah(Nasabah data) async {
String url =
new Uri.http("$baseUrl", "/api/mstdebitur/${data.id}").toString();
final response = await client.put(url,
headers: {"Content-Type": "application/json"},
body: nasabahToJson(data));
if (response.statusCode == 200) {
return true;
} else {
return false;
}
}
Future<bool> deleteNasabah(int id) async {
String url = new Uri.http("$baseUrl", "/api/mstdebitur/$id").toString();
final response = await client.delete(url);
if (response.statusCode == 200) {
return true;
} else {
return false;
}
}
}

Pass user data to profile screen from firebase

I am tring to pas data to user profile screen from firebase
i have got error Unhandled Exception: 'package:cloud_firestore/src/collection_reference.dart': Failed assertion: line 116 pos 14: 'path.isNotEmpty': a document path must be a non-empty string
what do i need fix?
user prfile controller
lass ProfileController extends GetxController {
final Rx<Map<String, dynamic>> _user = Rx<Map<String, dynamic>>({});
Map<String, dynamic> get user => _user.value;
Rx<String> _uid = ''.obs;
updateUserID(String uid) {
_uid.value = uid;
getUserData();
}
void getUserData() async {
print("HELLO");
List<String> thumbnails = [];
// var myVideos = await firestore
// .collection('videos')
// .where('uid', isEqualTo: "9GFyxV41rkd0Iu0oy1tctobVNk92")
// .get();
//
// for (int i = 0; i < myVideos.docs.length; i++) {
// thumbnails.add((myVideos.docs[i].data() as dynamic)['thumbnail']);
// }
DocumentSnapshot userDoc =
await firestore.collection('users').doc(_uid.value).get();
final userData = userDoc.data()! as dynamic;
print(userData);
String name = userData['name'];
String profilePhoto = userData['profilePhoto'];
int likes = 0;
int followers = 0;
int following = 0;
bool isFollowing = false;
// for (var item in myVideos.docs) {
// likes += (item.data()['likes'] as List).length;
// }
// var followerDoc = await firestore
// .collection('users')
// .doc(_uid.value)
// .collection('followers')
// .get();
// var followingDoc = await firestore
// .collection('users')
// .doc(_uid.value)
// .collection('following')
// .get();
// followers = followerDoc.docs.length;
// following = followingDoc.docs.length;
// firestore
// .collection('users')
// .doc(_uid.value)
// .collection('followers')
// .doc(authController.user.uid)
// .get()
// .then(
// (value) {
// if (value.exists) {
// isFollowing = true;
// } else {
// isFollowing = false;
// }
// },
// );
_user.value = {
'followers': followers.toString(),
'following': following.toString(),
'isFollowing': isFollowing,
'likes': likes.toString(),
'profilePhoto': profilePhoto,
'name': name,
'thumbnails': thumbnails,
};
update();
}
followUser() async {
var doc = await firestore
.collection('users')
.doc(_uid.value)
.collection('followers')
.doc(authController.user.uid)
.get();
if (!doc.exists) {
await firestore
.collection('users')
.doc(_uid.value)
.collection('followers')
.doc(authController.user.uid)
.set({});
await firestore
.collection('users')
.doc(authController.user.uid)
.collection('following')
.doc(_uid.value)
.set({});
_user.value
.update('followers', (value) => (int.parse(value) + 1).toString());
} else {
await firestore
.collection('users')
.doc(_uid.value)
.collection('followers')
.doc(authController.user.uid)
.delete();
await firestore
.collection('users')
.doc(authController.user.uid)
.collection('following')
.doc(_uid.value)
.delete();
_user.value
.update('followers', (value) => (int.parse(value) - 1).toString());
}
_user.value.update('isFollowing', (value) => !value);
update();
}
}
auth Controller
class AuthController extends GetxController {
static AuthController instance = Get.find(); //TODO 2
var displayName = '';
var displayPhoto = '';
String myId = '';
late Rx<User?> _user; //TODO 1
User get user => _user.value!; //TODO 3
Rx<File?>? pickedImageVal;
File? get profilePhoto => pickedImageVal!.value;
FirebaseAuth auth = FirebaseAuth.instance;
User? get userProfile => auth.currentUser;
var isSignedIn = false.obs;
var _googleSignIn = GoogleSignIn();
var googleAccount = Rx<GoogleSignInAccount?>(null);
var firebaseStorage = FirebaseStorage.instance;
var firestore = FirebaseFirestore.instance;
// var authController = AuthController.instance;
#override
void onReady() {
super.onReady();
_user = Rx<User?>(firebaseAuth.currentUser);
_user.bindStream(firebaseAuth.authStateChanges());
ever(_user, _setInitialScreen);
}
_setInitialScreen(User? user) {
if (user == null) {
Get.offAll(OnboardingPage());
} else {
Get.offAll(const Home());
}
}
#override
void onInit() {
displayName = userProfile != null ? userProfile!.displayName! : '';
super.onInit();
}
void pickImage() async {
final pickedImage =
await ImagePicker().pickImage(source: ImageSource.gallery);
if (pickedImage != null) {
Get.snackbar(
'プロファイル写真', 'You have successfully selected your profile picture!');
}
pickedImageVal = Rx<File?>(File(pickedImage!.path));
}
Future<String> _uploadToStorage(File image) async {
Reference ref =
firebaseStorage.ref().child('profilePics').child(auth.currentUser!.uid);
UploadTask uploadTask = ref.putFile(image);
TaskSnapshot snap = await uploadTask;
String downloadUrl = await snap.ref.getDownloadURL();
return downloadUrl;
}
void signUp(String name, String email, String password, File? image) async {
try {
await auth
.createUserWithEmailAndPassword(email: email, password: password)
.then((value) {
displayName = name;
auth.currentUser!.updateDisplayName(name);
});
isSignedIn = true.obs;
String downloadUrl = await _uploadToStorage(profilePhoto!);
model.UserM user = model.UserM(
name: name,
email: email,
uid: auth.currentUser!.uid,
profilePhoto: downloadUrl,
);
await firestore
.collection('users')
.doc(auth.currentUser!.uid)
.set(user.toJson());
update();
Get.offAll(() => Root());
} on FirebaseAuthException catch (e) {
String title = e.code.replaceAll(RegExp('-'), ' ').capitalize!;
String message = '';
if (e.code == 'weak-password') {
message = 'The password provided is too weak.';
} else if (e.code == 'email-already-in-use') {
message = ('The account already exists for that email.');
} else {
message = e.message.toString();
}
Get.snackbar(title, message,
snackPosition: SnackPosition.BOTTOM,
backgroundColor: kPrimaryColor,
colorText: Colors.white);
} catch (e) {
Get.snackbar('Error occured!', e.toString(),
snackPosition: SnackPosition.BOTTOM,
backgroundColor: kPrimaryColor,
colorText: Colors.white);
}
}
void signIn(String email, String password) async {
try {
await auth
.signInWithEmailAndPassword(email: email, password: password)
.then((value) => displayName = userProfile!.displayName!);
isSignedIn = true.obs;
myId = userProfile!.uid; //TODO 4
update();
Get.offAll(() => Root());
} on FirebaseAuthException catch (e) {
String title = e.code.replaceAll(RegExp('-'), ' ').capitalize!;
String message = '';
if (e.code == 'wrong-password') {
message = 'Invalid Password. Please try again!';
} else if (e.code == 'user-not-found') {
message =
('The account does not exists for $email. Create your account by signing up.');
} else {
message = e.message.toString();
}
Get.snackbar('ユーザー名が存在しません。', 'アカウントを作成してください。',
snackPosition: SnackPosition.BOTTOM,
backgroundColor: kPrimaryColor,
colorText: Colors.white);
} catch (e) {
//TODO; what is Get.snackbar.e.tostring(), means?
Get.snackbar(
'Error occured!',
e.toString(),
snackPosition: SnackPosition.BOTTOM,
backgroundColor: kPrimaryColor,
colorText: Colors.white,
);
}
}
void resetPassword(String email) async {
try {
await auth.sendPasswordResetEmail(email: email);
Get.back();
} on FirebaseAuthException catch (e) {
String title = e.code.replaceAll(RegExp('-'), ' ').capitalize!;
String message = '';
if (e.code == 'user-not-found') {
message =
('The account does not exists for $email. Create your account by signing up.');
} else {
message = e.message.toString();
}
Get.snackbar(title, message,
snackPosition: SnackPosition.BOTTOM,
backgroundColor: kPrimaryColor,
colorText: Colors.white);
} catch (e) {
Get.snackbar('Error occured!', e.toString(),
snackPosition: SnackPosition.BOTTOM,
backgroundColor: kPrimaryColor,
colorText: Colors.white);
}
}
void signInWithGoogle() async {
try {
googleAccount.value = await _googleSignIn.signIn();
print(googleAccount.value);
displayName = googleAccount.value!.displayName!;
displayPhoto = googleAccount.value!.photoUrl!;
isSignedIn.value = true;
update(); // <-- without this the isSignedin value is not updated.
} catch (e) {
Get.snackbar('Error occured!', e.toString(),
snackPosition: SnackPosition.BOTTOM,
backgroundColor: kPrimaryColor,
colorText: Colors.white);
}
}
void signout() async {
try {
await auth.signOut();
await _googleSignIn.signOut();
displayName = '';
isSignedIn.value = false;
update();
Get.offAll(() => Root());
} catch (e) {
Get.snackbar('Error occured!', e.toString(),
snackPosition: SnackPosition.BOTTOM,
backgroundColor: kPrimaryColor,
colorText: Colors.white);
}
}
}
//
// extension StringExtention on String{
// String capitalizedString(){
// return'${this[0].toUpperCase()}${this.substring(1)}';
// }
// }
user profile screen
class ProfileScreen extends StatefulWidget {
final String uid;
ProfileScreen({Key? key, required this.uid}) : super(key: key);
#override
State<ProfileScreen> createState() => _ProfileScreenState();
}
class _ProfileScreenState extends State<ProfileScreen> {
final ProfileController profileController = Get.put(ProfileController());
#override
void initState() {
super.initState();
profileController.updateUserID(widget.uid);
}
#override
Widget build(BuildContext context) {
return GetBuilder<ProfileController>(
init: ProfileController(),
builder: (controller) {
// if (controller.user.isEmpty) {
// return Center(
// child: CircularProgressIndicator(),
// );
// }
print(controller.user);
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.black12,
leading: Icon(Icons.person_add_alt_1_outlined),
actions: [
Icon(Icons.more_horiz),
],
title: Text(controller.user['name'].toString()),
),
body: SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ClipOval(
child: CachedNetworkImage(
fit: BoxFit.cover,
imageUrl: controller.user['profilePhoto']
.toString(),
height: 100,
width: 100,
placeholder: (context, url) =>
CircularProgressIndicator(),
errorWidget: (context, url, error) =>
Icon(Icons.error)),
)
],
),
SizedBox(
height: 15,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
children: [
Text(controller.user['following'].toString()),
SizedBox(
height: 5,
),
Text('following'),
],
),
Container(
color: Colors.black54,
width: 1,
height: 15,
margin: EdgeInsets.symmetric(horizontal: 15),
),
Column(
children: [
Text(controller.user['followers'].toString()),
SizedBox(
height: 5,
),
Text('follower'),
],
),
Container(
color: Colors.black54,
width: 1,
height: 15,
margin: EdgeInsets.symmetric(horizontal: 15),
),
Column(
children: [
Text(controller.user['likes'].toString()),
SizedBox(
height: 5,
),
Text('likes'),
],
)
],
),
SizedBox(
height: 15,
),
Container(
width: 140,
height: 47,
decoration: BoxDecoration(
border: Border.all(
color: Colors.black12,
),
),
child: Center(
child: InkWell(
onTap: () {
// if (widget.uid == authController.user.uid) {
// authController.signOut();
// } else {
// controller.followUser();
},
// },
child: const Text(
"",
// widget.uid == authController.user.uid
// ? 'sign out'
// controller.user['isFollowing']
// ? 'unfollow'
// : 'follow',
),
),
),
),

Unhandled Exception: NoSuchMethodError: The method '[]' was called on null. Tried calling: []("username")

Bonjour tout le monde,
I have this error message in my console, I searched for several days without finding the answer.
error message:
Unhandled Exception: NoSuchMethodError: The method '[]' was called on null. Tried calling:
Can you help me? here is my code:
final auth = FirebaseAuth.instance;
final googleSignIn = GoogleSignIn();
final ref = FirebaseFirestore.instance.collection('Users');
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
Users currentUserModel;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized(); // after upgrading flutter this is now necessary
await Firebase.initializeApp();
// enable timestamps in firebase
runApp(MyApp());
}
Future<Null> _ensureLoggedIn(BuildContext context) async {
GoogleSignInAccount user = googleSignIn.currentUser;
if (user == null) {
user = await googleSignIn.signInSilently();
}
if (user == null) {
await googleSignIn.signIn();
await tryCreateUserRecord(context);
}
if (await auth.currentUser == null) {
final GoogleSignInAccount googleUser = await googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth = await googleUser
.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
await auth.signInWithCredential(credential);
}
}
Future<Null> _silentLogin(BuildContext context) async {
GoogleSignInAccount user = googleSignIn.currentUser;
if (user == null) {
user = await googleSignIn.signInSilently();
await tryCreateUserRecord(context);
}
if (await auth.currentUser == null && user != null) {
final GoogleSignInAccount googleUser = await googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth = await googleUser
.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
await auth.signInWithCredential(credential);
}
}
Future<Null> _setUpNotifications() async {
if (Platform.isAndroid) {
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print('on message $message');
},
onResume: (Map<String, dynamic> message) async {
print('on resume $message');
},
onLaunch: (Map<String, dynamic> message) async {
print('on launch $message');
},
);
_firebaseMessaging.getToken().then((token) {
print("Firebase Messaging Token: " + token);
FirebaseFirestore.instance
.collection("Users")
.doc(currentUserModel.id)
.update({"androidNotificationToken": token});
});
}
}
Future<void> tryCreateUserRecord(BuildContext context) async {
GoogleSignInAccount user = googleSignIn.currentUser;
if (user == null) {
return null;
}
DocumentSnapshot userRecord = await ref.doc(user.id).get();
if (userRecord.data == null) {
// no user record exists, time to create
String userName = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Center(
child: Scaffold(
appBar: AppBar(
leading: Container(),
title: Text('Fill out missing data',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold)),
backgroundColor: Colors.white,
),
body: ListView(
children: <Widget>[
Container(
child: CreateAccount(),
),
],
)),
)),
);
if (userName != null || userName.length != 0) {
ref.doc(user.id).set({
"id": user.id,
"username": userName,
"photoUrl": user.photoUrl,
"email": user.email,
"displayName": user.displayName,
"bio": "",
"followers": {},
"following": {},
});
}
userRecord = await ref.doc(user.id).get();
}
currentUserModel = Users.fromDocument(userRecord);
return null;
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyApp',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or press Run > Flutter Hot Reload in IntelliJ). Notice that the
// counter didn't reset back to zero; the application is not restarted.
primarySwatch: Colors.blue,
buttonColor: Colors.pink,
primaryIconTheme: IconThemeData(color: Colors.black)),
home: HomePage(title: 'Myapp'),
);
}
}
class HomePage extends StatefulWidget {
HomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_HomePageState createState() => _HomePageState();
}
PageController pageController;
class _HomePageState extends State<HomePage> {
int _page = 0;
bool triedSilentLogin = false;
bool setupNotifications = false;
Scaffold buildLoginPage() {
return Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.only(top: 240.0),
child: Column(
children: <Widget>[
Text(
'MyApp',
style: TextStyle(
fontSize: 60.0,
fontFamily: "Billabong",
color: Colors.black),
),
Padding(padding: const EdgeInsets.only(bottom: 100.0)),
GestureDetector(
onTap: login,
child: Image.asset(
"assets/images/google_signin_button.png",
width: 225.0,
),
)
],
),
),
),
);
}
#override
Widget build(BuildContext context) {
if (triedSilentLogin == false) {
silentLogin(context);
}
if (setupNotifications == false && currentUserModel != null) {
setUpNotifications();
}
return (googleSignIn.currentUser == null || currentUserModel == null)
? buildLoginPage()
: Scaffold(
body: PageView(
children: [
Container(
color: Colors.white,
child: Feed(),
),
Container(color: Colors.white, child: SearchPage()),
Container(
color: Colors.white,
child: Uploader(),
),
Container(
color: Colors.white, child: ActivityFeedPage()),
Container(
color: Colors.white,
child: ProfilePage(
userId: googleSignIn.currentUser.id,
)),
],
controller: pageController,
physics: NeverScrollableScrollPhysics(),
onPageChanged: onPageChanged,
),
bottomNavigationBar: CupertinoTabBar(
backgroundColor: Colors.white,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home,
color: (_page == 0) ? Colors.black : Colors.grey),
title: Container(height: 0.0),
backgroundColor: Colors.white),
BottomNavigationBarItem(
icon: Icon(Icons.search,
color: (_page == 1) ? Colors.black : Colors.grey),
title: Container(height: 0.0),
backgroundColor: Colors.white),
BottomNavigationBarItem(
icon: Icon(Icons.add_circle,
color: (_page == 2) ? Colors.black : Colors.grey),
title: Container(height: 0.0),
backgroundColor: Colors.white),
BottomNavigationBarItem(
icon: Icon(Icons.star,
color: (_page == 3) ? Colors.black : Colors.grey),
title: Container(height: 0.0),
backgroundColor: Colors.white),
BottomNavigationBarItem(
icon: Icon(Icons.person,
color: (_page == 4) ? Colors.black : Colors.grey),
title: Container(height: 0.0),
backgroundColor: Colors.white),
],
onTap: navigationTapped,
currentIndex: _page,
),
);
}
void login() async {
await _ensureLoggedIn(context);
setState(() {
triedSilentLogin = true;
});
}
void setUpNotifications() {
_setUpNotifications();
setState(() {
setupNotifications = true;
});
}
void silentLogin(BuildContext context) async {
await _silentLogin(context);
setState(() {
triedSilentLogin = true;
});
}
void navigationTapped(int page) {
//Animating Page
pageController.jumpToPage(page);
}
void onPageChanged(int page) {
setState(() {
this._page = page;
});
}
#override
void initState() {
super.initState();
pageController = PageController();
}
#override
void dispose() {
super.dispose();
pageController.dispose();
}
}
and my user.dart:
class Users {
final String email;
final String id;
final String photoUrl;
final String username;
final String displayName;
final String bio;
final Map followers;
final Map following;
const Users(
{this.username,
this.id,
this.photoUrl,
this.email,
this.displayName,
this.bio,
this.followers,
this.following});
factory Users.fromDocument(DocumentSnapshot doc) {
return Users(
id: doc.id,
username: doc.data()['username'],
email: doc.data()['email'],
photoUrl: doc.data()['photoUrl'],
displayName: doc.data()['displayName'],
bio: doc.data()['bio'],
followers: doc.data()['followers'],
following: doc.data()['following'],
);
}
}
I think the problem is with my factory in the user.dart file, but I'm not sure ... I'm still looking ... thanks for your help