this is my chatscreen code
import 'package:flutter/material.dart';
import 'package:messenger/helperfunction/sharedpref_helper.dart';
import 'package:messenger/services/database.dart';
import 'package:random_string/random_string.dart';
class ChatScreen extends StatefulWidget {
final String chatWithusername, name;
ChatScreen(this.chatWithusername, this.name);
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
String? chatRoomId, messageId = "";
String? myName, myProfilePic, myUserName, myEmail;
TextEditingController messageEditingController = TextEditingController();
getMyInfoFromSharedPreference() async {
myName = await SharedPreferenceHelper().getDisplayName();
myProfilePic = await SharedPreferenceHelper().getUserProfileUrl();
myUserName = await SharedPreferenceHelper().getUserName();
myEmail = await SharedPreferenceHelper().getUserEmail();
chatRoomId = getChatRoomIdByUsername(widget.chatWithusername, myUserName);
}
getChatRoomIdByUsername(String? a, String? b) {
if (a!.substring(0, 1).codeUnitAt(0) > b!.substring(0, 1).codeUnitAt(0)) {
return "$b\_$a";
} else {
return "$a\_$b";
}}
addMessage(bool sentClicked) {
if (messageEditingController.text != "") {
String message = messageEditingController.text;
var lastMessageTs = DateTime.now();
Map<String, dynamic> messageInfoMap = {
"message": message,
"sentBy": myUserName,
'ts': lastMessageTs,
"imgUrl": myProfilePic
};
//Gentrate the message id
if (messageId == "") {
messageId = randomAlphaNumeric(12);
}
DatabaseMethods()
.addMessage(chatRoomId!, messageId!, messageInfoMap)
.then((value) {
Map<String, dynamic>? lastMessageInfoMap = {
"lastmessage": message,
"lastMessageSendTs": lastMessageTs,
"lastMessageSendBy": myUserName
};
DatabaseMethods()
.updateLastmessageSend(chatRoomId!, lastMessageInfoMap);
if (sentClicked) {
messageEditingController.text = "";
messageId = "";
}
});
}
}
getAnfSentMessages() async {}
doThisOnlaunch() async {
await getMyInfoFromSharedPreference();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.name),
),
body: Container(
child: Stack(
children: [
Container(
alignment: Alignment.bottomCenter,
child: Container(
color: Colors.black.withOpacity(0.8),
padding: EdgeInsets.symmetric(
horizontal: 6,
vertical: 8,
),
child: Row(
children: [
Expanded(
child: TextField(
controller: messageEditingController,
onChanged: (value) {
addMessage(false);
},
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
hintText: " Type a message",
hintStyle: TextStyle(
color: Colors.white.withOpacity(0.6))),
),
),
GestureDetector(
onTap: () {
addMessage(true);
},
child: Icon(Icons.send, color: Colors.white))
],
),
),
)
],
),
),
);
}
}
This is my DataBase;
import 'package:cloud_firestore/cloud_firestore.dart';
// ignore: unused_import
import 'package:firebase_core/firebase_core.dart';
class DatabaseMethods {
Future addUserInfoToDB(
String userId, Map<String, dynamic> userInfoMap) async {
return FirebaseFirestore.instance
.collection("users")
.doc(userId)
.set(userInfoMap);
}
Future<Stream<QuerySnapshot>> getUserByUserName(String username) async {
return FirebaseFirestore.instance
.collection("users")
.where("username", isEqualTo: username)
.snapshots();
}
Future addMessage(String chatRoomId, String messageId,
Map<String, dynamic> messageInfoMap) async {
return FirebaseFirestore.instance
.collection("chatRooms")
.doc(chatRoomId)
.collection("chats")
.doc(messageId)
.set(messageInfoMap);
}
updateLastmessageSend(
String chatRoomId, Map<String, dynamic> lastMessageInfoMap) {
return FirebaseFirestore.instance
.collection("chatRooms")
.doc(chatRoomId)
.update(lastMessageInfoMap);
}
createChatRoom(
String chatRoomId, Map<String, dynamic> chatRoomInfoMap) async {
final snapShot = await FirebaseFirestore.instance
.collection("chatrooms")
.doc(chatRoomId)
.get();
if (snapShot.exists) {
//chatroom already exits
return true;
} else {
//chatRoom does not exit:
return FirebaseFirestore.instance
.collection("chatrooms")
.doc(chatRoomId)
.set(chatRoomInfoMap);
}
}
}
when i run this code and start typing in textformfield, i am getting this following error:
'''
════════ Exception caught by widgets
═══════════════════════════════════════════
The following _CastError was thrown while calling onChanged:
Null check operator used on a null value
When the exception was thrown, this was the stack
#0 _ChatScreenState.addMessage
package:messenger/view/chatscreen.dart:54
#1 _ChatScreenState.build.<anonymous closure>
package:messenger/view/chatscreen.dart:103
#2 EditableTextState._formatAndSetValue
package:flutter/…/widgets/editable_text.dart:2298
#3 EditableTextState.updateEditingValue
package:flutter/…/widgets/editable_text.dart:1749
#4 TextInput._handleTextInputInvocation
package:flutter/…/services/text_input.dart:1351
'''
After typed, when i clicked sent icon i am getting error like this:
'''
════════ Exception caught by gesture
═══════════════════════════════════════════
Null check operator used on a null value
════════════════════════════════════════════════════════════════════════
'''
can anyone help to solve this issue
After digging into your code I can see that this function is never called
doThisOnlaunch() async {
await getMyInfoFromSharedPreference();
}
So the getMyInfoFromSharedPreference() function is never called
So chatRoomId is not initialized and it will always be null Because of this code
String? chatRoomId, messageId = "";
And in this method you are using the ! on chatRoomId which is null.
DatabaseMethods()
.addMessage(chatRoomId!, messageId!, messageInfoMap).then((value) {...
So this is what causes the error.
Solution
Call tis method on initState like
String? chatRoomId, messageId = "";
String? myName, myProfilePic, myUserName, myEmail;
TextEditingController messageEditingController = TextEditingController();
#override
void initState() {
super.initState();
doThisOnlaunch();
}
.
.
.
or just initiate chatRoomId with a value and declare them as not nullable String
String chatRoomId="", messageId = "";
Note that this second solution will just stop the error but your code will not function properly
Somewhere you used ! on a variable and that variable is null. Check the error where it is.
getChatRoomIdByUsername(String? a, String? b) {
if (a!.substring(0, 1).codeUnitAt(0) > b!.substring(0, 1).codeUnitAt(0)) {
return "$b\_$a";
} else {
return "$a\_$b";
}}
Why are you allowing nullable variables if the function depends on this?
getChatRoomIdByUsername({required String a,required String b}) {
if (a.substring(0, 1).codeUnitAt(0) > b.substring(0, 1).codeUnitAt(0)) {
return "$b\_$a";
} else {
return "$a\_$b";
}
}
Related
I'm trying to grab data from firebase (users collection -> uid document-> Summoner Info collection -> id document -> summonerName field) and display the summonerName's rank. Below is the screen that is causing the error:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:first_project/network/api.dart';
import 'package:first_project/screens/summoner_search.dart';
import 'package:flutter/material.dart';
import 'set_summoner_name.dart';
class MainScreen extends StatefulWidget {
const MainScreen({Key? key}) : super(key: key);
static const id = '/mainScreen';
#override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
CollectionReference usersCollection =
FirebaseFirestore.instance.collection('users');
final FirebaseAuth _auth = FirebaseAuth.instance;
late User loggedInUser;
bool summonerExists = false;
void getCurrentUser() {
try {
final user = _auth.currentUser;
if (user != null) {
loggedInUser = user;
print(loggedInUser.email);
}
} catch (e) {
print(e);
}
// here you write the codes to input the data into firestore
}
#override
void initState() {
getCurrentUser();
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Main Screen'),
actions: [
IconButton(
onPressed: () => Navigator.pushNamed(context, SummonerSearch.id),
icon: Icon(Icons.search_off_rounded),
),
],
),
body: Center(
child: StreamBuilder(
stream: usersCollection
.doc(_auth.currentUser!.uid)
.collection('Summoner Info')
.snapshots(),
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
// checkIfSummonerExists(snapshot);
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
print('Reached Here!');
print(snapshot.data!.docs[0].data().toString());
return ListView(
children: snapshot.data!.docs.map((document) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ListTile(
title: Text('Name:' + document['summonerName']),
),
Card(
child: FutureBuilder<dynamic>(
future: DataModel()
.getWholeRank(document['summonerName']),
builder: (context, snapshot) {
String tier;
String rank;
try {
//if successful, the player is ranked and has data
if (snapshot.hasData) {
tier = snapshot.data![0]['tier'];
rank = snapshot.data![0]['rank'];
} else {
return CircularProgressIndicator();
}
if (tier == 'CHALLENGER' || tier == 'MASTER') {
rank = '';
}
return Center(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(tier),
SizedBox(width: 2.0),
Text(rank),
],
),
);
} catch (e) {
//if unsuccessful call from api, means the player is unranked and json is empty
return Center(
child: Text('Unranked'),
);
}
},
),
),
],
);
}).toList(),
);
},
),
),
),
);
}
}
In the code above, I notice I am getting the Stack Overflow error starting at the 'Card' line about 3/4 of the way down, which is where I grab the data from the database and fetch the data from the API. If I comment all of that out and just display the summonerName, I get no error.
For the API functions as reference, below here is the code of the getWholeRank method
Future<dynamic> fetchRank(String name) async {
name = removeSpaces(name);
String id = await fetchByName(name, 'id');
NetworkHelper networkHelper = NetworkHelper(
'https://na1.api.riotgames.com/lol/league/v4/entries/by-summoner/$id?api_key=$api_key');
var rankData = await networkHelper.getRankData();
return rankData;
}
Future<dynamic> getWholeRank(summonerName) async {
var rankData = await rankObj.fetchRank(summonerName);
return rankData;
}
and below this is my NetworkHelper class:
import 'package:http/http.dart' as http;
import 'dart:convert';
class NetworkHelper {
NetworkHelper(this.url);
final String url;
Future getData({String ch = 'default'}) async {
http.Response response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
String data = response.body;
// print(data);
var decodedData = jsonDecode(data);
if (ch == 'default') {
print(decodedData);
return decodedData; //returns map of data
} else {
//Options: id, accountID, name, puuid, profileIconID, revisionDate, summonerLevel,
print(decodedData[ch]);
return decodedData[ch];
}
} else {
print('Status code: ');
print(response
.statusCode); //if doesn't work, it will print status code (200 is good, 400 etc. is bad)
}
}
Future getRankData({String ch = 'default'}) async {
http.Response response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
String data = response.body;
var decodedData = jsonDecode(data);
// print(decodedData[0]['tier']);
return decodedData;
} else {
print('Failed! Status code: ');
print(response
.statusCode); //if doesn't work, it will print status code (200 is good, 400 etc. is bad)
}
}
}
If anyone could help me understand why I'm getting the stack overflow error, it would be much appreciated!!
So I fixed the error, and it was because I was passing an object into the future argument and in the stack trace, there were lots of DataModel objects being initialized, causing the stack overflow. I fixed it in the getWholeRank method by replacing rankObj, a DataModel object, to the 'this' keyword.
I'm trying to build an app with Flutter and Firebase password-less authentication. I'm able to receive the email from Firebase but when I like on the link
auth.isSignInWithEmailLink(link) says false.
My pubspec.yaml firebase dependencies
firebase_core: ^1.0.3
firebase_auth: ^1.0.2
firebase_dynamic_links: ^2.0.2
Here is the full Login code
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_dynamic_links/firebase_dynamic_links.dart';
class LoginPage extends StatefulWidget {
static String tag = "login page";
#override
LoginPageState createState() => new LoginPageState();
}
class LoginPageState extends State<LoginPage> with WidgetsBindingObserver {
String _email;
final _formKey = GlobalKey<FormState>();
final _scaffoldKey = GlobalKey<ScaffoldState>();
#override
void initState() {
super.initState();
this.initDynamicLinks();
WidgetsBinding.instance.addObserver(this);
}
void initDynamicLinks() async {
FirebaseDynamicLinks.instance.onLink(
onSuccess: (PendingDynamicLinkData dynamicLink) async {
final Uri deepLink = dynamicLink?.link;
if (deepLink != null) {
print('DeepLink: ' + deepLink.path);
await _signInWithEmailAndLink(deepLink.toString());
}
}, onError: (OnLinkErrorException e) async {
print('onLinkError');
print(e.message);
});
}
#override
Widget build(BuildContext context) {
final snackBarEmailSent = SnackBar(content: Text('Email Sent!'));
final snackBarEmailNotSent = SnackBar(
content: Text('Email Not Sent. Error.'),
);
final email = TextFormField(
keyboardType: TextInputType.emailAddress,
autofocus: false,
validator: (value) {
if (value.isEmpty) return "Email cannot be empty";
return null;
},
onSaved: (value) => _email = value,
decoration: InputDecoration(
hintText: 'Email',
prefixIcon: Icon(Icons.mail),
contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
),
);
final loginButton = Padding(
padding: EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
child: Text("Send Verification Email"),
onPressed: (() async => await validateAndSave()
? ScaffoldMessenger.of(context).showSnackBar(snackBarEmailSent)
: ScaffoldMessenger.of(context)
.showSnackBar(snackBarEmailNotSent))),
);
final loginForm = Form(
key: _formKey,
child: ListView(
shrinkWrap: true,
padding: EdgeInsets.only(left: 24, right: 24),
children: <Widget>[
SizedBox(height: 50),
email,
SizedBox(height: 40),
loginButton
],
),
);
return Scaffold(
key: _scaffoldKey,
backgroundColor: Colors.white,
body: Center(child: loginForm));
}
Future<bool> validateAndSave() async {
final FormState form = _formKey.currentState;
if (form.validate()) {
form.save();
bool sent = await _sendSignInWithEmailLink();
return sent;
}
return false;
}
Future<bool> _sendSignInWithEmailLink() async {
final FirebaseAuth auth = FirebaseAuth.instance;
try {
auth.sendSignInLinkToEmail(
email: _email,
actionCodeSettings: ActionCodeSettings(
url: 'https://<MyApp>.page.link/<key>',
handleCodeInApp: true,
androidInstallApp: true,
androidMinimumVersion: "12"));
} catch (e) {
_showDialog(e.toString());
return false;
}
print(_email + "<< sent");
return true;
}
Future<void> _signInWithEmailAndLink(link) async {
final FirebaseAuth auth = FirebaseAuth.instance;
// final PendingDynamicLinkData data =
// await FirebaseDynamicLinks.instance.getInitialLink();
// final Uri deepLink = data?.link;
print('Link: ' + link);
bool validLink = auth.isSignInWithEmailLink(link);
print('Is Valid Link: ' + validLink.toString());
if (validLink) {
try {
print('email:' + _email);
print('link:' + link);
await auth.signInWithEmailLink(email: _email, emailLink: link);
} catch (e) {
print('Error' + e);
_showDialog(e.toString());
}
}
}
void _showDialog(String error) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: new Text("Error"),
content: new Text("Please Try Again.Error code: " + error),
actions: <Widget>[
new TextButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
}
Let me know what I'm missing here.
Thank you!
Try the plugin app_links along with firebase_dynamic_links.
Sample Code
Future<bool> retrieveDynamicLinkAndSignIn() async {
try {
await Future.delayed(const Duration(seconds: 2));
final _appLinks = AppLinks(
onAppLink: (Uri uri, String url) {
appLogs('onAppLink[$url][$uri]');
},
);
final deepLink = await _appLinks.getInitialAppLink();
appLogs('appLinks.uri[$deepLink]');
if (deepLink != null) {
bool validLink =
_firebaseAuth.isSignInWithEmailLink(deepLink.toString());
if (validLink) {
String email = SPService.instance.getString('email') ?? '';
appLogs('retrieveDynamicLinkAndSignIn[$email]');
if (email.isEmpty) {
return false;
}
SPService.instance.setString('email', '');
final firebase_auth.UserCredential userCredential =
await _firebaseAuth.signInWithEmailLink(
email: email,
emailLink: deepLink.toString(),
);
if (userCredential.user != null) {
await _setUserFromFirebaseUser();
logLogin(SignUp.email, true);
return true;
} else {
logLogin(SignUp.email, false);
AppToast.info(strings.noCredentialsWereFound);
}
} else {
appLogs('Link is not valid');
AppToast.info(strings.noCredentialsWereFound);
}
} else {
appLogs('retrieveDynamicLinkAndSignIn.deepLink[$deepLink]');
}
} catch (e, s) {
AppToast.error(null, e, s);
}
return false;
}
Hello Im very to the flutter framework, so please let me know if im going wrong anywhere and the appropriate way of doing the things.
this is a drawerPage.dar file
In this file im trying to call a function getData for retrieving the data from firebase,this fucntion is in Database.dart file.
Database.dart
In the Database.dart file i wrote the getData function inside which im retrieving a particular record from the firebase and storing in a global variable. And then im trying to print the global variable in the drawerPage.dart file.But here when ever i run the program, for the first time the variable is having a null value and upon hot reload the actual value is getting stored in the variable.Please let me know how can i get rid of this problem.
output
drawerPageOutput
drawerPage.dart
import 'package:attendee/constants.dart';
import 'package:attendee/models/userdeails.dart';
import 'package:attendee/pages/profile.dart';
import 'package:attendee/services/authentication_service.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:attendee/services/database.dart';
import 'package:provider/provider.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:attendee/pages/userdetails.dart';
class StudentDashboard extends StatefulWidget {
#override
_StudentDashboardState createState() => _StudentDashboardState();
}
class _StudentDashboardState extends State<StudentDashboard> {
userdetails userdetail;
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
final AuthenticationService _auth = AuthenticationService();
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
DatabaseService().getData('email');
final drawerHeader = UserAccountsDrawerHeader(
accountName: Text(userName),
accountEmail: Text('${result}'),
currentAccountPicture
: CircleAvatar(
child: FlutterLogo(size: 42.0),
backgroundColor: Colors.white,
);
final drawerItems = ListView(
children: <Widget>[
drawerHeader,
ListTile(
title: Row(
children: <Widget>[
Icon(Icons.perm_identity_outlined),
Text(' Profile'),
],
),
onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (context)=>Profile())),
),
ListTile(
title: Text('To page 2'),
onTap: () => Navigator.of(context).push(_NewPage(2)),
),
ListTile(
title:Row(
children: <Widget>[
Icon(Icons.exit_to_app_rounded),
Text(' Logout'),
],
),
onTap: () async {
await _auth.signOut();
Navigator.of(context).pushNamed('/homepage');
},
),
],
);
return StreamProvider<List<userdetails>>.value(
value: DatabaseService().students,
initialData: [],
child: SafeArea(
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.lightGreen,
title: Text('Student Welcome'),
actions: <Widget>[
TextButton.icon(
onPressed: () async {
await _auth.signOut();
Navigator.of(context).pushNamed('/homepage');
},
icon: Icon(Icons.person),
label: Text('Logout'))
],
),
body:
UserDetails(),
drawer: GestureDetector(
onTap: display,
child: Drawer(
child: drawerItems,
),
),
),
),
);
}
display() async{
await DatabaseService().getData('email');
}
}
// <Null> means this route returns nothing.
class _NewPage extends MaterialPageRoute<Null> {
_NewPage(int id)
: super(builder: (BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Page $id'),
elevation: 1.0,
),
body: Center(
child: Text('Page $id'),
),
);
});
}
database.dart
import 'package:attendee/models/userdeails.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart';
import '../constants.dart';
class DatabaseService{
final String uid;
DatabaseService({this.uid});
//collection reference
final CollectionReference user_details=FirebaseFirestore.instance.collection('users');`
final CollectionReference tutor_details` `=FirebaseFirestore.instance.collection("tutors");`
Future updateStudentData(String fullname,String mobilenumber,String `email,String rollno,String tutorid,String role) async {`
return await user_details.doc(uid).set({
'fullname' : fullname,
'mobilenumber': mobilenumber,
'email' : email,
'rollno': rollno,
'tutorid': tutorid,
'role' : role,//FMERT series
});
}
Future updateTutorData(String fullname,String mobilenumber,String `email,String rollno,String tutorid,String role) async {`
return await tutor_details.doc(uid).set({
'fullname' : fullname,
'mobilenumber': mobilenumber,
'email' : email,
'rollno': rollno,
'tutorid': tutorid,
'role' : role,//FMERT series
});
}
//studentDetails from snapshot
List<userdetails> _studentDetailsFromSnapshot(QuerySnapshot snapshot){
return snapshot.docs.map((doc){
return userdetails(
fullname: doc.data()['fullname'] ?? '',
mobilenumber: doc.data()['mobilenumber'] ?? '',
email: doc.data()['email'] ?? '',
rollno: doc.data()['rollno'] ?? '',
tutorid: doc.data()['tutorid'] ?? '',
//role: doc.data()['role'] ?? '',
);
}).toList();
}
//get students stream
Stream<List<userdetails>> get students {
return user_details.snapshots()
.map(_studentDetailsFromSnapshot);
}
//tutorsDetails from snapshot
List<userdetails> _tutorDetailsFromSnapshot(QuerySnapshot snapshot){
return snapshot.docs.map((doc){
return userdetails(
fullname: doc.data()['fullname'] ?? '',
mobilenumber: doc.data()['mobilenumber'] ?? '',
email: doc.data()['email'] ?? '',
rollno: doc.data()['rollno'] ?? '',
tutorid: doc.data()['tutorid'] ?? '',
);
}).toList();
}
//get tutors stream
Stream<List<userdetails>> get tutors {
return user_details.snapshots()
.map(_studentDetailsFromSnapshot);
}
void display() {
tutor_details.get().then((querySnapshot) {
querySnapshot.docs.forEach((result) {
print(result.data());
});
});
}
getData (String string) async{
String userId = await FirebaseAuth.instance.currentUser.uid;
final document = isTutor ? `FirebaseFirestore.instance.doc('tutors/$userId') :`
await FirebaseFirestore.instance.doc('users/$userId');
document.get().then((DocumentSnapshot) async {
if(string =='role') {
checkRole = DocumentSnapshot.data()[string].toString();
print('$checkRole inside getData Function');
//return checkRole;
print(checkRole);
}
else {
print(result);
result = await DocumentSnapshot.data()[string].toString();
print('${DocumentSnapshot.data()[string].toString()} in the `database else block');`
//return result;
}
//print(document("name"));
});
}
}
After changes
terminaloutput
draweroutput
""when ever i run the program, for the first time the variable is having a null value and upon hot reload the actual value is getting stored in the variable""
When we try to get data from http / https request, it takes some time. Meanwhile the page gets loaded and you get null values.
You can use Provider package to resolve this issue, or try the below code. Please add the below code in your drawerPage.dart.
What I have done below is made getData() return type. Only on receiving a value from this function, _loadOnce will change to false & final screen will be shown.
Database.dart
Future<bool> getData (String string) async{
String userId = await FirebaseAuth.instance.currentUser.uid;
final document = isTutor ? `FirebaseFirestore.instance.doc('tutors/$userId') :`
await FirebaseFirestore.instance.doc('users/$userId');
document.get().then((DocumentSnapshot) async {
if(string =='role') {
checkRole = DocumentSnapshot.data()[string].toString();
print('$checkRole inside getData Function');
//return checkRole;
print(checkRole);
return true;
}
else {
print(result);
result = await DocumentSnapshot.data()[string].toString();
print('${DocumentSnapshot.data()[string].toString()} in the `database else block');`
//return result;
return false;
}
//print(document("name"));
});
}
}
/// create a new variable.
bool _loadOnce = true;
/// shift your code `DatabaseService().getData('email');`
#override
void didChangeDependencies() {
if(_loadOnce == true) {
DatabaseService().getData('email').then((value) {
if(value == true){
setState(() {
_loadOnce = false;
});
} else {
/// you can write your code here
setState(() {
_loadOnce = false;
});
}
)}
}
super.didChangeDependencies();
}
Below code will show a spinner till the time all the code gets executed and values are retreived.
/// in your main page under Scaffold
body: _loadOnce == true
? Center(
child: CircularProgressIndicator(
backgroundColor: Theme.of(context).primaryColor,
),
)
: UserDetails(),
As per the screenshot once I open the screen it gives me the error "The getter 'email' was called on null." but if I just click back button, then open the screen again, it works well without any error,
the purpose of the screen is the account owner see the notes that was sent to him from the admin account
This is the error appears only one time after opening the app
Here the same screen without any error
Here is the codes in dart where the tap to screen exists
import 'package:flutter/cupertino.dart' show CupertinoIcons;
import 'package:flutter/material.dart';
import 'package:notification_permissions/notification_permissions.dart';
import 'package:provider/provider.dart';
import 'package:rate_my_app/rate_my_app.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import '../../app.dart';
import '../../common/config.dart';
import '../../common/constants.dart';
import '../../common/tools.dart';
import '../../generated/l10n.dart';
import '../../models/index.dart' show AppModel, User, UserModel, WishListModel;
import '../../routes/flux_navigate.dart';
import '../../screens/blogs/post_screen.dart';
import '../../services/index.dart';
import '../../widgets/common/webview.dart';
import '../custom/smartchat.dart';
import '../index.dart';
import '../users/user_point.dart';
import 'currencies.dart';
import 'language.dart';
import 'notification.dart';
import '../../common/config.dart' as config;
import 'package:cespohm/screens/bywaleed/booking_admin_screen.dart';
import 'package:cespohm/screens/bywaleed/docor_note_tap.dart';
import 'package:cespohm/screens/bywaleed/user_search_new_screen.dart';
import 'package:cespohm/screens/bywaleed/doctor_notes_user_screen.dart';
class SettingScreen extends StatefulWidget {
final List<dynamic> settings;
final String background;
final User user;
final VoidCallback onLogout;
final bool showChat;
SettingScreen({
this.user,
this.onLogout,
this.settings,
this.background,
this.showChat,
});
#override
_SettingScreenState createState() {
return _SettingScreenState();
}
}
class _SettingScreenState extends State<SettingScreen>
with
TickerProviderStateMixin,
WidgetsBindingObserver,
AutomaticKeepAliveClientMixin<SettingScreen> {
#override
bool get wantKeepAlive => true;
final bannerHigh = 150.0;
bool enabledNotification = true;
final RateMyApp _rateMyApp = RateMyApp(
// rate app on store
minDays: 7,
minLaunches: 10,
remindDays: 7,
remindLaunches: 10,
googlePlayIdentifier: kStoreIdentifier['android'],
appStoreIdentifier: kStoreIdentifier['ios']);
void showRateMyApp() {
_rateMyApp.showRateDialog(
context,
title: S.of(context).rateTheApp,
// The dialog title.
message: S.of(context).rateThisAppDescription,
// The dialog message.
rateButton: S.of(context).rate.toUpperCase(),
// The dialog "rate" button text.
noButton: S.of(context).noThanks.toUpperCase(),
// The dialog "no" button text.
laterButton: S.of(context).maybeLater.toUpperCase(),
// The dialog "later" button text.
listener: (button) {
// The button click listener (useful if you want to cancel the click event).
switch (button) {
case RateMyAppDialogButton.rate:
break;
case RateMyAppDialogButton.later:
break;
case RateMyAppDialogButton.no:
break;
}
return true; // Return false if you want to cancel the click event.
},
// Set to false if you want to show the native Apple app rating dialog on iOS.
dialogStyle: const DialogStyle(),
// Custom dialog styles.
// Called when the user dismissed the dialog (either by taping outside or by pressing the "back" button).
// actionsBuilder: (_) => [], // This one allows you to use your own buttons.
);
}
#override
void initState() {
super.initState();
Future.delayed(Duration.zero, () async {
await checkNotificationPermission();
});
_rateMyApp.init().then((_) {
// state of rating the app
if (_rateMyApp.shouldOpenDialog) {
showRateMyApp();
}
});
}
// #override
// void dispose() {
// Utils.setStatusBarWhiteForeground(false);
// super.dispose();
// }
Future<void> checkNotificationPermission() async {
if (!isAndroid || isIos) {
return;
}
try {
await NotificationPermissions.getNotificationPermissionStatus()
.then((status) {
if (mounted) {
setState(() {
enabledNotification = status == PermissionStatus.granted;
});
}
});
} catch (err) {
printLog('[Settings Screen] : ${err.toString()}');
}
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
checkNotificationPermission();
}
}
/// Render the Admin Vendor Menu
Widget renderVendorAdmin() {
if (!(widget.user != null ? widget.user.isVendor ?? false : false)) {
return Container();
}
return Card(
color: Theme.of(context).backgroundColor,
margin: const EdgeInsets.only(bottom: 2.0),
elevation: 0,
child: ListTile(
onTap: () {
final String langCode =
Provider.of<AppModel>(context, listen: false).langCode;
if (unsupportedLanguages.contains(langCode)) {
final snackBar = SnackBar(
content: Text(
S.of(context).thisFeatureDoesNotSupportTheCurrentLanguage),
duration: const Duration(seconds: 1),
);
Scaffold.of(context).showSnackBar(snackBar);
return;
}
FluxNavigate.push(
MaterialPageRoute(
builder: (context) =>
Services().widget.getAdminVendorScreen(context, widget.user),
),
forceRootNavigator: true,
);
},
leading: Icon(
Icons.dashboard,
size: 24,
color: Theme.of(context).accentColor,
),
title: Text(
S.of(context).vendorAdmin,
style: const TextStyle(fontSize: 16),
),
trailing: Icon(
Icons.arrow_forward_ios,
size: 18,
color: Theme.of(context).accentColor,
),
),
);
}
/// Render the custom profile link via Webview
/// Example show some special profile on the woocommerce site: wallet, wishlist...
Widget renderWebViewProfile() {
if (widget.user == null) {
return Container();
}
var base64Str = Utils.encodeCookie(widget.user.cookie);
var profileURL = '${serverConfig["url"]}/my-account?cookie=$base64Str';
return Card(
color: Theme.of(context).backgroundColor,
margin: const EdgeInsets.only(bottom: 2.0),
elevation: 0,
child: ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => WebView(
url: profileURL, title: S.of(context).updateUserInfor),
),
);
},
leading: Icon(
CupertinoIcons.profile_circled,
size: 24,
color: Theme.of(context).accentColor,
),
title: Text(
S.of(context).updateUserInfor,
style: const TextStyle(fontSize: 16),
),
trailing: Icon(
Icons.arrow_forward_ios,
color: Theme.of(context).accentColor,
size: 18,
),
),
);
}
Widget renderItem(value) {
IconData icon;
String title;
Widget trailing;
Function() onTap;
bool isMultiVendor = kFluxStoreMV.contains(serverConfig['type']);
switch (value) {
case 'bookingAdmin':
if (widget.user == null ) {
return Container();
}
else if(widget.user.email == config.adminEmail || widget.user.email == config.adminEmailTwo && widget.user != null )
{
icon = FontAwesomeIcons.keyboard;
title = S.of(context).checkout;
trailing =
const Icon(Icons.arrow_forward_ios, size: 18, color: kGrey600);
onTap = () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => const BookingAdminScreen()),
);
}
else {
return Container();
}
break;
case 'addDoctorNote':
if (widget.user == null ) {
return Container();
}
else if(widget.user.isVendor && widget.user != null )
{
icon = FontAwesomeIcons.edit;
title = S.of(context).continueToShipping;
trailing =
const Icon(Icons.arrow_forward_ios, size: 18, color: kGrey600);
onTap = () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => const UserSearchNewScreen()),
);
}
else {
return Container();
}
break;
/// here is the tap to the screen where there is the error
case 'yourDoctorNotes':
if (widget.user == null || widget.user.email == config.adminEmail || widget.user.email == config.adminEmailTwo ) {
return Container();
}
else if(!widget.user.isVendor)
{
icon = FontAwesomeIcons.notesMedical;
title = S.of(context).french;
trailing =
const Icon(Icons.arrow_forward_ios, size: 18, color: kGrey600);
onTap = () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => DoctorNoteUserScreen(senderUser: widget.user,)),
);
}
else {
return Container();
}
break;
case 'chat':
here is the dart code of the screen where is the error
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:date_format/date_format.dart';
import 'package:flutter/material.dart';
import 'package:cespohm/models/bywaleed_model/user_search_new_model.dart';
import 'package:cespohm/models/bywaleed_model/user_search_new_provider.dart';
import 'package:cespohm/models/entities/user.dart';
import 'package:firebase_auth/firebase_auth.dart' as firebase_auth;
import 'package:provider/provider.dart';
import '../../generated/l10n.dart' as word;
import '../../models/index.dart' show AppModel, Store, User, UserModel ;
final _fireStore = FirebaseFirestore.instance;
firebase_auth.User loggedInUser;
class DoctorNoteUserScreen extends StatelessWidget {
final User senderUser;
DoctorNoteUserScreen({
Key key,
this.senderUser,
}) : super(key: key);
#override
Widget build(BuildContext context) {
final userSearchProvider = Provider.of<UserSearchProvider>(context);
return Scaffold(
appBar: AppBar(
title: Text(
word.S.of(context).french,
style: TextStyle(
color: Colors.white, fontSize: 18.0, fontWeight: FontWeight.w400),
),
leading: Center(
child: GestureDetector(
child: const Icon(
Icons.arrow_back_ios,
color: Colors.white,
),
onTap: () => Navigator.pop(context),
),
),
),
body: StreamBuilder<List<UserSearchModel>>(
stream: userSearchProvider.userstwo,
builder: (context, snapshot) {
if (!snapshot.hasData ) {
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
Theme.of(context).primaryColor),
),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(7.0),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
SizedBox(
height: 40.0,
),
Text(word.S.of(context).french,
style: TextStyle(fontSize: 18.0)),
SizedBox(
height: 15.0,
),
Divider(
thickness: 1.0,
)
],
),
),
Container(
child: ListTile(
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 15.0,
),
Container(
child: Text(snapshot.data[index].doctorNote!=null?snapshot.data[index].doctorNote: 'No Notes Yet',
style: TextStyle(fontSize: 20.0)),
),
],
),
),
),
],
),
);
});
}
}),
);
}
}
here is the dart code of the service
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:cespohm/models/bywaleed_model/user_search_new_model.dart';
import 'package:cespohm/models/bywaleed_model/user_search_new_provider.dart';
import 'package:cespohm/models/user_model.dart';
class UserSearchService {
final FirebaseFirestore _db = FirebaseFirestore.instance;
final userModel = UserModel();
//Get Entries
Stream<List<UserSearchModel>> getEntries(){
return _db
.collection('users')
.orderBy('firstName', descending: false)
.snapshots()
.map((snapshot) => snapshot.docs
.map((doc) => UserSearchModel.fromJson(doc.data()))
.toList());
}
/// here is the firebase collection where the error exists
Stream<List<UserSearchModel>> getEntriesTwo(){
return _db
.collection('users').where('email', isEqualTo: userModel.user.email)
.snapshots()
.map((snapshot) => snapshot.docs
.map((doc) => UserSearchModel.fromJson(doc.data()))
.toList());
}
}
here is the model
import 'package:cloud_firestore/cloud_firestore.dart';
class UserSearchModel {
final String date;
final String firstName;
final String lastName;
final String phone;
final String email;
final String searchKey;
final String doctorNote;
final String bYDoctor;
final String uID;
UserSearchModel(
{this.date,
this.firstName,
this.lastName,
this.phone,
this.email,
this.searchKey,
this.doctorNote,
this.bYDoctor,
this.uID});
// creating a Trip object from a firebase snapshot
UserSearchModel.fromSnapshot(DocumentSnapshot snapshot) :
date = snapshot['date'],
firstName = snapshot['firstName'].toDate(),
lastName = snapshot['lastName'].toDate(),
phone = snapshot['phone'],
email = snapshot['email'],
searchKey = snapshot['searchKey'],
doctorNote = snapshot['doctorNote'],
bYDoctor = snapshot['bYDoctor'],
uID = snapshot.id;
factory UserSearchModel.fromJson(Map<String, dynamic> json) {
return UserSearchModel(
date: json['createdAt'],
firstName: json['firstName'],
lastName: json['lastName'],
phone: json['phone'],
email: json['email'],
searchKey: json['searchKey'],
doctorNote: json['doctorNote'],
bYDoctor: json['bYDoctor'],
uID: json['uID']);
}
Map<String, dynamic> toMap() {
return {
'createdAt': date,
'firstName': firstName,
'lastName': lastName,
'phone': phone,
'email': email,
'searchKey': searchKey,
'doctorNote': doctorNote,
'bYDoctor': bYDoctor,
'uID': uID,
};
}
}
Here is the provider
import 'package:flutter/material.dart';
import 'package:cespohm/models/bywaleed_model/user_search_new_model.dart';
import 'package:cespohm/models/user_model.dart';
import 'package:cespohm/services/bywaleed/user_search_new_service.dart';
import 'package:uuid/uuid.dart';
class UserSearchProvider with ChangeNotifier {
final userSearchService = UserSearchService();
final userModel = UserModel();
DateTime _date;
String _firstName;
String _lastName;
String _phone;
String _email;
String _searchKey;
String _doctorNote;
String _bYDoctor;
String _uID;
var uuid = Uuid();
//Getters
DateTime get date => _date;
String get firstName => _firstName;
String get lastName => _lastName;
String get phone => _phone;
String get email => _email;
String get searchKey => _searchKey;
String get doctorNote => _doctorNote;
String get byDoctor => _bYDoctor;
String get uID => _uID;
Stream<List<UserSearchModel>> get users => userSearchService.getEntries();
Stream<List<UserSearchModel>> get userstwo => userSearchService.getEntriesTwo();
//Setters
set changeDate(DateTime date) {
_date = date;
notifyListeners();
}
set changeFirstName(String firstName) {
_firstName = firstName;
notifyListeners();
}
set changeLastName(String lastName) {
_lastName = lastName;
notifyListeners();
}
set changePhone(String phone) {
_phone = phone;
notifyListeners();
}
set changeEmail(String email) {
_email = email;
notifyListeners();
}
set changeSearchKey(String searchKey) {
_searchKey = searchKey;
notifyListeners();
}
set changeDoctorNote(String doctorNote) {
_doctorNote = doctorNote;
notifyListeners();
}
set changeBYDoctor(String bYDoctor) {
_bYDoctor = bYDoctor;
notifyListeners();
}
set changeuID(String uID) {
_uID = uID;
notifyListeners();
}
//Functions
loadAll(UserSearchModel userSearchModel) {
if (userSearchModel != null) {
_date = DateTime.parse(userSearchModel.date);
_firstName = userSearchModel.firstName;
_lastName = userSearchModel.lastName;
_phone = userSearchModel.phone;
_email = userSearchModel.email;
_searchKey = userSearchModel.searchKey;
_doctorNote = userSearchModel.doctorNote;
_bYDoctor = userModel.user.email;
_uID = userSearchModel.uID;
} else {
_date = DateTime.now();
_firstName = null;
_lastName = null;
_phone = null;
_email = null;
_searchKey = null;
_doctorNote = null;
_bYDoctor = null;
_uID = null;
}
}
saveEntry() {
if (_email == null) {
//Add
var newUserModel = UserSearchModel(
date: _date.toIso8601String(),
firstName: _firstName,
lastName: _lastName,
phone: _phone,
email: _email,
searchKey: _searchKey,
doctorNote: _doctorNote,
bYDoctor: _bYDoctor,
uID: _uID);
print(newUserModel.email);
userSearchService.setEntry(newUserModel);
} else {
//Edit
var updatedEntry = UserSearchModel(
date: _date.toIso8601String(),
firstName: _firstName,
lastName: _lastName,
phone: _phone,
email: _email,
searchKey: _searchKey,
doctorNote: _doctorNote,
bYDoctor: _bYDoctor,
uID: _uID);
userSearchService.setEntry(updatedEntry);
}
}
removeEntry(String entryId) {
userSearchService.removeEntry(entryId);
}
}
You need to make sure your User object is initialised. This error appears because user.email is accessed, but your User object is null. Make sure your code considers loading time for the user object if it comes from the API, and has appropriate checks for the case when user == null.
I am trying to upload image in firebase storage getting the image from image picker plugin by accessing camera. Image is not uploading. I also add I change the firebase rules so only authenticated users can upload the image. Git hub Repo. I used the image uploading logic defined at the auth_screen.dart Line No 48 to 59[I commented out for time being]. I also add as i add these line my other firebase fuctions which are running prefectly before. getting the errors.
auth_screen.dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
// import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/services.dart';
import '../widgets/auth/auth_form.dart';
class AuthScreen extends StatefulWidget {
#override
_AuthScreenState createState() => _AuthScreenState();
}
class _AuthScreenState extends State<AuthScreen> {
final _auth = FirebaseAuth.instance;
var _isLoading = false;
void _submitAuthForm(
String email,
String password,
String userName,
File userImage,
bool isLogin,
BuildContext ctx,
) async {
dynamic authResult;
try {
setState(() {
_isLoading = true;
});
if (isLogin) {
authResult = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
} else {
print(email);
print(userName);
print(userImage.path);
authResult = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
// final FirebaseStorage storage = FirebaseStorage(
// app: FirebaseStorage.instance.app,
// storageBucket: 'gs://chatapp-1b780.appspot.com',
// );
// final StorageReference ref2 =
// storage.ref().child('userimage').child('${authResult.user.id}.jpg');
// final StorageUploadTask uploadTask = ref2.putFile(userImage);
// uploadTask.onComplete
// .then((value) => print(value))
// .catchError((error) => print(error));
// print(uploadTask.lastSnapshot.error.toString());
// ///...
// final ref = FirebaseStorage.instance
// .ref()
// .child('user_image')
// .child(authResult.user.id + '.jpg');
// await ref.putFile(userImage).onComplete;
///
await FirebaseFirestore.instance
.collection('users')
.doc(authResult.user.uid)
.set({
'username': userName,
'email': email,
});
}
} on PlatformException catch (error) {
var message = 'An error occured,Please check your credentials';
if (error.message != null) {
setState(() {
_isLoading = false;
});
message = error.message;
}
print(message);
} catch (error) {
setState(() {
_isLoading = false;
});
Scaffold.of(ctx).showSnackBar(
SnackBar(
content: Text(error.toString()),
backgroundColor: Theme.of(ctx).errorColor,
),
);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).primaryColor,
body: AuthForm(_submitAuthForm, _isLoading),
);
}
}
image being picked using image picker from auth/auth_form.dart to user_image_picker.dart where i added the argument so the image is passed down.
auth/authform.dart
import 'package:flutter/material.dart';
import 'dart:io';
import '../pickers/user_image_picker.dart';
class AuthForm extends StatefulWidget {
final bool isLoading;
final void Function(String email, String password, String userName,
File userImage, bool isLogin, BuildContext ctx) submitFn;
AuthForm(this.submitFn, this.isLoading);
#override
_AuthFormState createState() => _AuthFormState();
}
class _AuthFormState extends State<AuthForm> {
final _formKey = GlobalKey<FormState>();
var _isLogin = true;
String _userEmail = '';
String _userName = '';
String _userPassword = '';
File _userImageFile;
void _pickedImage(File image) {
_userImageFile = image;
}
void _trysubmit() {
final isValid = _formKey.currentState.validate();
FocusScope.of(context).unfocus();
if (_userImageFile == null && !_isLogin) {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text('Please Pick an Image'),
backgroundColor: Theme.of(context).errorColor,
),
);
return;
}
if (isValid) {
_formKey.currentState.save();
print(_userEmail);
print(_userPassword);
widget.submitFn(_userEmail.trim(), _userPassword.trim(), _userName.trim(),
_userImageFile, _isLogin, context);
print(_userEmail);
print(_userPassword);
}
}
#override
Widget build(BuildContext context) {
return Center(
child: Card(
margin: EdgeInsets.all(20),
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
if (!_isLogin)
UserImagePicker(
imagePickFn: _pickedImage,
),
TextFormField(
key: ValueKey('emailAdress'),
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'Email address',
),
validator: (value) {
if (value.isEmpty || !value.contains('#')) {
return 'Please return a valid email address';
}
return null;
},
onSaved: (newValue) {
_userEmail = newValue;
},
),
if (!_isLogin)
TextFormField(
key: ValueKey('userName'),
decoration: InputDecoration(labelText: 'Username'),
validator: (value) {
if (value.isEmpty || value.length < 4) {
return 'Please Enter at least 4 characters';
}
return null;
},
onSaved: (newValue) {
_userName = newValue;
},
),
TextFormField(
key: ValueKey('password'),
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
validator: (value) {
if (value.isEmpty || value.length < 7) {
return 'Please Enter at least 7 characters';
}
return null;
},
onSaved: (newValue) {
_userPassword = newValue;
},
),
SizedBox(
height: 12,
),
if (widget.isLoading) CircularProgressIndicator(),
if (!widget.isLoading)
RaisedButton(
onPressed: _trysubmit,
child: Text((_isLogin) ? 'Login' : 'SignUp'),
),
if (!widget.isLoading)
FlatButton(
textColor: Theme.of(context).primaryColor,
child: Text(_isLogin
? 'Create new account'
: 'I already have an account'),
onPressed: () {
setState(() {
_isLogin = !_isLogin;
});
},
),
],
),
),
),
),
),
),
);
}
}
user_image_picker.dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class UserImagePicker extends StatefulWidget {
UserImagePicker({this.imagePickFn});
final void Function(File pickedImage) imagePickFn;
#override
_UserImagePickerState createState() => _UserImagePickerState();
}
class _UserImagePickerState extends State<UserImagePicker> {
File _image;
final picker = ImagePicker();
Future<void> getImage() async {
final pickedFile = await ImagePicker().getImage(source: ImageSource.camera);
setState(() {
_image = File(pickedFile.path);
});
widget.imagePickFn(_image);
}
#override
Widget build(BuildContext context) {
return Column(
children: [
CircleAvatar(
radius: 40,
backgroundColor: Colors.grey,
backgroundImage: _image != null ? FileImage(_image) : null,
),
FlatButton.icon(
onPressed: getImage,
icon: Icon(Icons.image),
label: Text('Add Image'),
textColor: Theme.of(context).primaryColor,
),
],
);
}
}
Since you asked me to show you how to upload images to Firebase Storage, I will show you the whole procedure including using the Image Picker plugin. This is how you should use Image Picker:
class PickMyImage{
static Future<File> getImage() async {
final image = await ImagePicker().getImage(
source: ImageSource.gallery,
maxHeight: 1500,
maxWidth: 1500,
);
if (image != null) {
return File(image.path);
}
return null;
}
}
This is how you can get and upload that image to firebase storage:
final File _myImage=await PickMyImage.getImage();
if(_myImage!=null){
final StorageReference firebaseStorageRef = FirebaseStorage.instance
.ref()
.child("user/${_auth.currentUser().uid}/i"); //i is the name of the image
StorageUploadTask uploadTask =
firebaseStorageRef.putFile(_myImage);
StorageTaskSnapshot storageSnapshot = await uploadTask.onComplete;
var downloadUrl = await storageSnapshot.ref.getDownloadURL();
if (uploadTask.isComplete) {
final String url = downloadUrl.toString();
print(url);
//You might want to set this as the _auth.currentUser().photourl
} else {
//error uploading
}
}
The issue i got because i am returning the ImagePicker() function of the file then gettting the image from camera then passing the file to the Fire Storage bucket.
In user_image_picker.dart
I written this
final pickedFile = await ImagePicker().getImage(source: ImageSource.camera);
Instead of i have to write this
final pickedFile = await picker.getImage(source: ImageSource.camera);