# #firebase #flutter #dart #firebase-authentication
Вопрос:
Я пытаюсь создать социальное приложение,в котором буду публиковать изображения.Когда я запускаю код, я сталкиваюсь с некоторыми проблемами при извлечении данных из firebase.
firebase_auth: ^3.1.1
firebase_core: ^1.6.0
google_sign_in: ^5.1.0
firebase_storage: ^10.0.3
cloud_firestore: ^2.5.3
firebase_analytics: ^8.3.2
lottie: ^1.1.0
image_picker: ^0.8.4
Выше приведены зависимости файлов pubspec.yaml.
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int _currentIndex = 0;
final List<Widget> _children = [
WeCareHomeScreen(),
WeCareReminder(),
Feed(),
Chatroom(),
Profile(),
];
@override
void initState() {
super.initState();
Provider.of<FirebaseOperations>(context, listen: false)
.initUserData(context)
.whenComplete(() {
setState(() {});
});
}
Widget build(BuildContext context) {
return Scaffold(
body: _children[_currentIndex],
bottomNavigationBar: CurvedNavigationBar(
index: 0,
height: 50.0,
items: <Widget>[
Icon(
Icons.home,
size: 25,
color: Colors.white,
),
Icon(
Icons.home,
size: 25,
color: Colors.white,
),
Icon(
Icons.home,
size: 25,
color: Colors.white,
),
Icon(
Icons.home,
size: 25,
color: Colors.white,
),
Icon(
Icons.home,
size: 25,
color: Colors.white,
),
],
color: Color.fromRGBO(241, 201, 57, 1.0),
buttonBackgroundColor: Colors.black,
backgroundColor: Colors.white,
animationCurve: Curves.easeInOut,
animationDuration: Duration(milliseconds: 600),
onTap: (index) {
setState(() {
_currentIndex = index;
});
}),
);
}
}
Выше находится рабочий стол.код файла дротика.
class Authentication with ChangeNotifier {
final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
late String userUid;
String get getUserUid => userUid;
Future logIntoAccount(String email, String password) async {
UserCredential userCredential = await firebaseAuth
.signInWithEmailAndPassword(email: email, password: password);
String userUid;
User? user = userCredential.user;
userUid = user!.uid;
print(userUid);
notifyListeners();
}
Future createAccount(String email, String password) async {
UserCredential userCredential = await firebaseAuth
.createUserWithEmailAndPassword(email: email, password: password);
User? user = userCredential.user;
userUid = user!.uid;
print('Created Account Uid => $userUid');
notifyListeners();
}
Future logoutViaEmail() {
return firebaseAuth.signOut();
}
Future signInWithGoogle() async {
final GoogleSignInAccount? googleSignInAccount =
await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAccount!.authentication;
final AuthCredential authCredential = GoogleAuthProvider.credential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken);
final UserCredential userCredential =
await firebaseAuth.signInWithCredential(authCredential);
final User? user = userCredential.user;
assert(user!.uid != null);
userUid = user!.uid;
print('Google User Uid => $userUid');
notifyListeners();
}
Future signOutWithGoogle() async {
return googleSignIn.signOut();
}
}
Above is Authentification.dart file.
class FirebaseOperations with ChangeNotifier {
late UploadTask imageUploadTask;
late String initUserEmail;
late String initUserImage;
late String initUserName;
String get getInitUserImage => initUserImage;
String get getInitUserName => initUserName;
String get getInitUserEmail => initUserEmail;
Future uploadUserAvatar(BuildContext context) async {
Reference imageReference = FirebaseStorage.instance.ref().child(
'userProfileAvatar/${Provider.of<LandingUtils>(context, listen:
false).getUserAvatar.path}/${TimeOfDay.now()}');
imageUploadTask = imageReference.putFile(
Provider.of<LandingUtils>(context, listen: false).getUserAvatar);
await imageUploadTask.whenComplete(() {
print('Image uploaded!');
});
imageReference.getDownloadURL().then((url) {
Provider.of<LandingUtils>(context, listen: false).userAvatarUrl =
url.toString();
print(
'the user profile avatar url => ${Provider.of<LandingUtils>(context, listen:
false).userAvatarUrl}');
notifyListeners();
});
}
Future createUserCollection(BuildContext context, dynamic data) async {
return FirebaseFirestore.instance
.collection('users')
.doc(Provider.of<Authentication>(context, listen: false).getUserUid)
.set(data);
}
Future initUserData(BuildContext context) async {
return FirebaseFirestore.instance
.collection('users')
.doc(Provider.of<Authentication>(context, listen: false).getUserUid)
.get()
.then((doc) {
print('Fetching user data');
initUserName = doc.data()!['username'];
initUserEmail = doc.data()!['useremail'];
initUserImage = doc.data()!['userimage'];
print(initUserName);
print(initUserEmail);
print(initUserImage);
notifyListeners();
});
}
Future uploadPostData(String postId, dynamic data) async {
return FirebaseFirestore.instance.collection('posts').doc(postId).set(data);
}
}
Above is the firebaseoperations.dart file.
Here once it printed ‘Fetching user Data’ in the console,it is showing ‘Unhandled Exception: Null check operator used on a null value’ error.
Also once the image is uploaded ,instead of printing the url of image, ‘*************’ is printed.
And ‘Unhandled Exception: LateInitializationError: Field ‘initUserName’ has not been initialized.’ is also printed.
It will me more helpful,if anyone pointout my mistakes and give me a solution.
Unhandled Exception: LateInitializationError: Field 'initUserName' has not been
initialized.
.
.
.
I/flutter (18214): Post image uploaded to storage
I/flutter (18214): Image uploaded
I/flutter (18214):
*************************************************************************************
*************************************************************************************
*********************************************
.
.
.
E/flutter (18214): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception:
LateInitializationError: Field 'initUserName' has not been initialized.
This is how the error looks.
class ProfileHelpers with ChangeNotifier {
ConstantColors constantColors = ConstantColors();
Widget headerProfile(
BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
print(snapshot.data);
return SizedBox(
height: MediaQuery.of(context).size.height * 0.26,
width: MediaQuery.of(context).size.width,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
height: 150.0,
width: 170.0,
child: Column(
children: [
GestureDetector(
onTap: () {},
child: CircleAvatar(
backgroundColor: constantColors.transparent,
radius: 38.0,
backgroundImage: NetworkImage(
'${Provider.of<FirebaseOperations>
(context).getInitUserImage}'),
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(
'Vijay',
//snapshot.data?['username'],
//snapshot.data!.data()['username'],
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 20.0),
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(EvaIcons.email,
color: constantColors.greenColor, size: 16),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
'username@gmail.com',
// snapshot.data!.get('useremail'),
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 12.0),
),
),
],
),
)
],
),
),
Above is the profile page code.
enter code here
class FeedHelpers with ChangeNotifier {
ConstantColors constantColors = ConstantColors();
Widget appBar(BuildContext context) {
return AppBar(
backgroundColor: constantColors.darkColor.withOpacity(0.6),
centerTitle: true,
actions: [
IconButton(
icon: Icon(Icons.camera_enhance_rounded,
color: constantColors.greenColor),
onPressed: () {
Provider.of<UploadPost>(context, listen: false)
.selectPostImageType(context);
})
],
title: RichText(
text: TextSpan(
text: 'Social ',
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 20.0,
),
children: <TextSpan>[
TextSpan(
text: 'Feed',
style: TextStyle(
color: constantColors.blueColor,
fontWeight: FontWeight.bold,
fontSize: 20.0,
))
]),
),
);
}
Widget feedBody(BuildContext context) {
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Container(
child: StreamBuilder<QuerySnapshot<Map<String, dynamic>>>(
stream:
FirebaseFirestore.instance.collection('posts').snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>>
snapshot) {
if (snapshot.connectionState == ConnectionState.waiting)
{
return Center(
child: SizedBox(
height: 500.0,
width: 400.0,
child:
Lottie.asset('assets/animations/loading.json'),
),
);
} else {
return loadPosts(context, snapshot);
}
},
),
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: constantColors.darkColor.withOpacity(0.6),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(18.0),
topRight: Radius.circular(18.0))),
),
),
);
}
Widget loadPosts(
BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
return ListView(
children: snapshot.data!.docs.map((DocumentSnapshot
documentSnapshot) {
Map<String, dynamic> data =
documentSnapshot.data()! as Map<String, dynamic>;
return Container(
height: MediaQuery.of(context).size.height * 0.62,
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(top: 8.0, left: 8.0),
child: Row(
children: [
GestureDetector(
child: CircleAvatar(
backgroundColor: constantColors.blueGreyColor,
radius: 20.0,
backgroundImage: NetworkImage(
'${Provider.of<UploadPost>
(context).getUploadPostImage}'),
// NetworkImage(documentSnapshot['userimage']),
),
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Container(
width: MediaQuery.of(context).size.width * 0.6,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: RichText(
text: TextSpan(
text: data['username'],
style: TextStyle(
color: constantColors.blueColor,
fontSize: 14.0,
fontWeight: FontWeight.bold),
children: <TextSpan>[
TextSpan(
text: ' , 12 hours ago',
style: TextStyle(
color:
constantColors.lightColor
.withOpacity(0.8)))
]),
)),
Container(
child: Text(
data['username'],
style: TextStyle(
color: constantColors.greenColor,
fontWeight: FontWeight.bold,
fontSize: 16.0,
),
),
),
],
),
),
)
],
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Container(
height: MediaQuery.of(context).size.height * 0.46,
width: MediaQuery.of(context).size.width,
child: FittedBox(
// child: Image.network(downloadURL.toString()),
child: Image.network(data['postimage'], scale:
2))),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Padding(
padding: const EdgeInsets.only(left: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width: 80.0,
child: Row(
children: [
GestureDetector(
child: Icon(
FontAwesomeIcons.heart,
color: constantColors.redColor,
size: 22.0,
),
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
'0',
style: TextStyle(
color: constantColors.whiteColor,
fontWeight: FontWeight.bold,
fontSize: 18.0),
),
)
],
),
),
Выше приведен файл feed_helper.
class UploadPost with ChangeNotifier {
TextEditingController captionController = TextEditingController();
ConstantColors constantColors = ConstantColors();
late File uploadPost;
late File uploadPostImage;
File get getUploadPostImage => uploadPostImage;
late String uploadPostImageUrl;
String get getUploadPostImageUrl => uploadPostImageUrl;
final picker = ImagePicker();
late UploadTask imagePostUploadTask;
Future pickUploadPostImage(BuildContext context, ImageSource
source) async {
final uploadPostImageVal = await picker.pickImage(source: source);
uploadPostImageVal == null
? print('Select Image')
: uploadPostImage = File(uploadPostImageVal.path);
print(uploadPostImageVal!.path);
uploadPostImage != null
? showPostImage(context)
: print('Image upload error');
notifyListeners();
}
Future uploadPostImageToFirebase() async {
Reference imageReference = FirebaseStorage.instance
.ref()
.child('posts/${uploadPostImage!.path}/${TimeOfDay.now()}');
imagePostUploadTask = imageReference.putFile(uploadPostImage!);
await imagePostUploadTask.whenComplete(() {
print('Post image uploaded to storage');
});
imageReference.getDownloadURL().then((imageUrl) {
uploadPostImageUrl = imageUrl;
print(uploadPostImageUrl);
});
notifyListeners();
}
Вышеуказанный файл является файлом uploadpost.dart
Ответ №1:
Проблема в том, что вы объявляете initUserName
поле как late
и пытаетесь получить к нему доступ перед его инициализацией (присвоением ему значения).
late
Ключевое слово говорит компилятору не беспокоиться о том, что переменная имеет значение null, потому что вы гарантируете, что присвоите ей значение, прежде чем пытаться получить к ней доступ.
Вы можете либо объявить initUserName
как String? initUserName
Таким образом, вы инициализируете его null
значением;
В противном случае вы можете убедиться, что задали ему такое значение: FirebaseOperations.initUserName = 'username';
прежде чем пытаться прочитать его значение
Комментарии:
1. на самом деле последнее ключевое слово означает , инициализированное при первом вызове, я прав ?
2. да, проблема в том, что в вашем случае переменная не имеет значения null, и вы неправильно инициализировали ее значением, поэтому, когда вы ее читаете, вы инициализируете переменную, не имеющую значения null
3. Даже если я объявлен как строка? initUserName , После «Извлечения пользовательских данных», он показывает Необработанное исключение: оператор проверки Null, используемый для значения null
4. ты сделал имя_пользователя! ( оператор взрыва ! ) в каком-нибудь месте?
5. initUserName = doc.data()![‘имя пользователя’]; Вот как я пытался получить имя пользователя. Если я ошибаюсь, поправьте меня!