I have a app and in that a chat function were chat working correctly and user name correctly diplayed. But now im trying to add a appBar and im getting an error. What I want is trying to build the name of the other user and not mine . So an example: I chat with my friend and in the app bar I wanna see his name so I know with how Im chatting . but how do I do that?. Heres how my chat app locks at the moment.
So heres how I use the username in chat bubble and it works fine :
class MessageBubble extends StatelessWidget {
MessageBubble(this.message, this.isMe, this.username, {this.key});
final Key key;
final String message;
final bool isMe;
String username;
#override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment:
isMe ? MainAxisAlignment.end : MainAxisAlignment.start,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: isMe ? Colors.grey[300] : Colors.black,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
topRight: Radius.circular(12),
bottomLeft:
!isMe ? Radius.circular(0) : Radius.circular(12),
bottomRight:
isMe ? Radius.circular(0) : Radius.circular(12),
)),
width: 140,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 16),
margin: EdgeInsets.symmetric(vertical: 4, horizontal: 8),
child: Column(
crossAxisAlignment:
isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: <Widget>[
Text(
username,
style: TextStyle(
color: isMe
? Colors.black
: Colors.white,
fontWeight: FontWeight.bold),
),
Text(
message,
style: TextStyle(
color: isMe
? Colors.black
: Colors.white),
textAlign: isMe ? TextAlign.end : TextAlign.start,
),
]))
]);
}
}
It displayed the correct username and the correct user message .
And heres how I wanna use it in the app bar:
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
CustomAppBar({this.key, this.username,this.isMe} ) : super(key: key);
final Key key;
final bool isMe;
final String username;
//String username;
#override
Widget build(BuildContext context) {
/// Build you AppBar widget here
return Scaffold(
appBar: AppBar(
elevation: 0,
automaticallyImplyLeading: false,
backgroundColor: Colors.white,
flexibleSpace: SafeArea(
child: Container(
padding: EdgeInsets.only(right: 16),
child: Row(
children: <Widget>[
IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back, color: Colors.black,),
),
SizedBox(width: 2,),
CircleAvatar(
backgroundImage: NetworkImage(
'https://randomuser.me/api/portraits/men/5.jpg'),
maxRadius: 20,
),
SizedBox(width: 12,),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
username, style: TextStyle(
fontSize: 16, fontWeight: FontWeight.w600),),
SizedBox(height: 6,),
Text("Online", style: TextStyle(
color: Colors.grey.shade600, fontSize: 13),),
],
),
),
Icon(Icons.settings, color: Colors.black54,),
],
),
),
),
),
);
}
#override
Size get preferredSize => Size.fromHeight(56);
}
And heres I wanna displayed it :
class ChatScreen extends StatelessWidget {
static const route = '/messages';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar:CustomAppBar()
,
body: Container(
child: Column(
children: <Widget>[
Expanded(child: Messages()),
NewMessage(),
],
),
),
);
}
}
I think you need to pass the username as String (and other parameters) in the CustomAppBar constructor like this:
class ChatScreen extends StatelessWidget {
static const route = '/messages';
final String username;
ChatScreen({#required this.username});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
username: username, // This is dynamic..
isMe: true,
),
body: Container(
child: Column(
children: <Widget>[
Expanded(child: Messages()),
NewMessage(),
],
),
),
);
}
}
EDIT
You need to get first the username of the other user and then you can create your ChatScreen:
//...some code...
String username = getUsername(); // This is your method to get the username
Navigator.of(context).push(MaterialPageRoute(builder: (context) => ChatScreen(username: username)));
In your code, when you are calling CustomAppBar() you are not passing any info/strings to it, that's causing your null error regarding a null string.
It should be i.e CustomAppBar (userName).
Related
I'm creating instagram app clone in flutter with firebase at backend. It's a beginner level project so the coding and structure is basic.
I am stuck at adding comment section under each post. I'm using streambuilder to display data and trying to create a function in which with every image is on the feed screen would have a comment box which is connected to the current-image document in cloud-firestore.
Below is my code and images of database:
class FeedScreen extends StatefulWidget {
const FeedScreen({Key? key}) : super(key: key);
#override
_FeedScreenState createState() => _FeedScreenState();
}
class _FeedScreenState extends State<FeedScreen> {
User? user = FirebaseAuth.instance.currentUser;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
bottomNavigationBar: BottomNavigation(),
appBar: AppBar(
backgroundColor: Colors.black,
automaticallyImplyLeading: false,
title: Text(
"Platform",
style: TextStyle(
color: Colors.white,
fontSize: 32.96,
fontWeight: FontWeight.w500,
fontFamily: 'Yaldevi',
),
),
),
body: StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection('users').snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot){
if(snapshot.hasData){
final List<DocumentSnapshot> documents = snapshot.data!.docs;
return ListView(
children: documents.map((doc) => SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListTile(
leading: doc['profileImage'] == null ?
CircleAvatar(
radius: 16.6,
backgroundColor: Colors.white24,
) :
CircleAvatar(
radius: 16.6,
backgroundImage: NetworkImage(
doc['profileImage']
)
),
title: Text(
doc['displayName'],
style: TextStyle(
color: Colors.white,
fontSize: 16.5,
)
),
subtitle: doc['title'] !=null ?
Text(
doc['title'],
style: TextStyle(
color: Colors.white,
fontSize: 12.5,
),
) :
Text(
"Some Title",
style: TextStyle(
color: Colors.white,
)
),
),
if(doc['photoURL'] != null) ... [
Container(
height: 400,
width: 400,
child: Image(
image: NetworkImage(
doc['photoURL'],
),
fit: BoxFit.contain,
)
),
IconButton(
icon: Icon(
Icons.mode_comment_outlined,
color: Colors.white,
),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(
builder: (context) =>
CommentSection(),
));
},
)
] else if(doc['photoURL'] == null) ...[
Container(
height: 400,
width: 400,
child: Image(
image: AssetImage(
"assets/images/placeholder.png"
),
fit: BoxFit.contain,
)
)
],
ListTile(
leading: Padding(
padding: EdgeInsets.only(bottom: 13.5 ),
child: Text( "# " +
doc['displayName'],
style: TextStyle(
color: Colors.white,
),
),
),
subtitle: Padding(
padding: EdgeInsets.only(bottom: 13.5),
child: doc['decsription'] != null ?
Text( ":" +
doc['decsription'],
style: TextStyle(
color: Colors.white,
)
) :
Text(
"Some Descritiption",
style: TextStyle(
color: Colors.white,
)
)
)
),
]
),
)).toList(),
);
} else {
return CircularProgressIndicator();
}
}
)
);
}
}
and here`s the comment screen code
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
class CommentSection extends StatefulWidget {
// const CommentSection({Key? key}) : super(key: key);
#override
_CommentSectionState createState() => _CommentSectionState();
}
class _CommentSectionState extends State<CommentSection> {
var username = ' ';
List photoURL = [];
User? user = FirebaseAuth.instance.currentUser;
CollectionReference userRef = FirebaseFirestore.instance.collection('users');
final _formKey = GlobalKey<FormState>();
late String comments = ' ';
sendComment() async {
final isValid = _formKey.currentState!.validate();
final name = user!.displayName;
var res = await userRef.where('userid', isEqualTo: user!.uid).get();
_formKey.currentState!.save();
var doc = userRef.doc('photoURL');
doc.set({
'comment' : comments,
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(top: 50),
child: TextFormField(
style: TextStyle(
color: Colors.white,
),
decoration: InputDecoration(
labelText: "Leave a Comment..",
labelStyle: TextStyle(
color: Colors.white,
)
),
onSaved: (value) {
comments = value!;
}
),
)
],
)
),
ElevatedButton.icon(
onPressed: sendComment,
icon: Icon(Icons.send,
color: Colors.white,
),
label: Text(
"Send"
))
],
)
),
);
}
}
That's a really broad use-case, and honestly a bit too broad to answer on Stack Overflow. I recommend focusing on a more concrete, specific problem.
For example, you mention in your comment:
I tried creating a separate collection for comment but the comment would be fetched for every image in database and I'm trying to save and retrieve the comment data for particular image
To allow reading only comments on a specific image, you'll need to associate each comment in the database with an image. The two most common approaches for this are:
Create a document for each image in a top-level collection, and then create a subcollection under that document for the comments on that specific image.
Create a single top-level comments collection, and store the ID of the image in each comment document.
So I have this code here and I would like to display post details from firebase for the post which I have clicked on, but instead, it lists post details for every single post in the database one after another.
Can anyone help me figure out how I can make it so that when A post is clicked, details will show for only the post which was clicked, and not for all of the posts? Any help would be greatly appreciated, thank you.
The Info I would like to display on the post is
postTitle
postDesc
postAuthor
Here is what the firebase looks like
Code Here:
import 'package:tennis_event_app/services/crud.dart';
import 'package:tennis_event_app/views/create_blog.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
CrudMethods crudMethods = new CrudMethods();
QuerySnapshot? blogSnapshot;
#override
void initState() {
crudMethods.getData()?.then((result) {
blogSnapshot = result;
setState(() {});
});
super.initState();
}
Widget blogsList() {
return Container(
child: ListView.builder(
padding: EdgeInsets.only(top: 24),
itemCount: blogSnapshot!.docs.length,
itemBuilder: (context, index) {
return BlogTile(
author: blogSnapshot!.docs[index].get('author'),
title: blogSnapshot!.docs[index].get('title'),
desc: blogSnapshot!.docs[index].get('desc'),
imgUrl: blogSnapshot!.docs[index].get('imgUrl'),
);
},
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Flutter",
style: TextStyle(fontSize: 22),
),
Text(
"Blog",
style: TextStyle(fontSize: 22, color: Colors.blue),
)
],
),
backgroundColor: Colors.transparent,
elevation: 0.0,
),
body: Container(
child: blogSnapshot != null
? blogsList()
: Container(
child: Center(
child: CircularProgressIndicator(),
))),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => CreateBlog()));
},
),
);
}
}
class BlogTile extends StatelessWidget {
final String imgUrl, title, desc, author;
BlogTile(
{required this.author,
required this.desc,
required this.imgUrl,
required this.title});
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(bottom: 16, right: 16, left: 16),
child: Stack(
children: <Widget>[
Container(
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(8)),
child: Image.network(
imgUrl,
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
height: 170,
),
),
),
Container(
height: 170,
decoration: BoxDecoration(
color: Colors.black45.withOpacity(0.3),
borderRadius: BorderRadius.circular(6)),
),
Container(
height: 170,
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
title,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 25, fontWeight: FontWeight.w500),
),
SizedBox(height: 4),
Text(
'$desc',
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w400),
),
SizedBox(
height: 4,
),
Text(author),
],
)),
Container(
child: SizedBox(
height: 170,
width: MediaQuery.of(context).size.width,
child: TextButton(
style: TextButton.styleFrom(
textStyle: const TextStyle(fontSize: 20),
),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => DetailPage()));
},
child: const Text(''),
),
),
),
],
),
);
}
}
class DetailPage extends StatefulWidget {
#override
_DetailPageState createState() => _DetailPageState();
}
class _DetailPageState extends State<DetailPage> {
CrudMethods crudMethods = new CrudMethods();
QuerySnapshot? blogSnapshot;
#override
void initState() {
crudMethods.getData()?.then((result) {
blogSnapshot = result;
setState(() {});
});
super.initState();
}
Widget blogsList2() {
return Container(
child: ListView.builder(
padding: EdgeInsets.only(top: 24),
itemCount: blogSnapshot!.docs.length,
itemBuilder: (context, index) {
return PageContent(
postAuthor: blogSnapshot!.docs[index].get('postAuthor'),
postTitle: blogSnapshot!.docs[index].get('postTitle'),
postDesc: blogSnapshot!.docs[index].get('postDesc'),
imgUrl: blogSnapshot!.docs[index].get('imgUrl'),
);
},
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Flutter",
style: TextStyle(fontSize: 22),
),
Text(
"Blog",
style: TextStyle(fontSize: 22, color: Colors.blue),
)
],
),
backgroundColor: Colors.transparent,
elevation: 0.0,
),
body: Container(
child: blogSnapshot != null
? blogsList2()
: Container(
child: Center(
child: CircularProgressIndicator(),
))),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => CreateBlog()));
},
),
);
}
}
class PageContent extends StatelessWidget {
final String imgUrl, postTitle, postDesc, postAuthor;
PageContent(
{required this.postAuthor,
required this.postDesc,
required this.imgUrl,
required this.postTitle});
#override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(bottom: 16, right: 16, left: 16),
child: Card(
child: ListTile(
title: Text(
postTitle,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 25, fontWeight: FontWeight.w500),
),
subtitle: Text(
'$postDesc',
style: TextStyle(fontSize: 17, fontWeight: FontWeight.w400),
),
)
)
);
}
}
I also reference crud.dart in that code, so incase you need it, here it is:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:collection';
class CrudMethods {
Future<void> addData(blogData) async {
print(blogData);
FirebaseFirestore.instance
.collection("blogs")
.add(blogData)
.then((value) => print(value))
.catchError((e) {
print(e);
});
}
getData() async {
return await FirebaseFirestore.instance
.collection("blogs")
.orderBy("ts", descending: true)
.get();
}
}
Thank you again for any help!
First I would recommend to modelize your data in an object for exemple a class Article that is easier to serialize and manipulate.
Then instead of requesting another time the database you should save your data in a List<Article> for example then you only update this list on refresh from your main page. That way you don'y manipulate a QuerySnapshot or Future but just your list of objects.
Finally and to answer your question, you could simply pass the clicked item Article to your details page and only display its content. Because here, you have the same construction as your main page with the same request that is resent.
Usually you can build your route like that (adding a parameter to your details with the index you clicked on for example)
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => DetailPage(article: _data[i])));
},
Here is an article on serialization from Flutter docs, it shows how to build your model with the toMap, toJson and fromJson methods.
I want to write the User's email under the User's name in the Navigation drawer, but I cannot access the email in Text Widget
I used this code for fetching user email id from Firebase but unable to write inside Text
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
firebase_auth.FirebaseAuth firebaseAuth = firebase_auth.FirebaseAuth.instance;
Future<void> signOut() async {
await firebaseAuth.signOut();
}
dynamic user;
String userEmail;
getCurrentUserInfo() async {
user = await firebaseAuth.currentUser;
userEmail = user.email;
print(userEmail);
return userEmail;
}
static var chartdisplay;
bool isSwitched = true;
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: Padding(
padding: EdgeInsets.symmetric(horizontal: 15),
child: Builder(
builder: (context) => IconButton(
icon: Image.asset(
"assets/images/menu.png",
),
onPressed: () => Scaffold.of(context).openDrawer(),
),
),
),
backgroundColor: const Color(0xffe8e5af),
elevation: 0,
centerTitle: false,
titleSpacing: 0,
),
drawer: new Drawer(
child: new ListView(
padding: EdgeInsets.zero,
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(vertical: 50, horizontal: 30),
color: const Color(0xffe8e5af),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
CircleAvatar(
radius: 46,
backgroundColor: Colors.white,
child: CircleAvatar(
backgroundImage: AssetImage('assets/images/avatar.jpg'),
radius: 40,
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Nabia Salman',
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: 13,
color: const Color(0xff000000),
fontWeight: FontWeight.w700,
),
textAlign: TextAlign.left,
),
Text(
//"${user.email}",
"nabia.salman99#gmail.com",
style: TextStyle(
fontFamily: 'Montserrat',
fontSize: 9,
color: const Color(0xff000000),
),
textAlign: TextAlign.left,
),
],
),
],
),
),
This is how my screen looks like
Please help me out in finding the solution for this as I am new to Flutter
Thank you in advance
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I am currently developing a chat app. The problem is, that when someone types something it shows randomly on the chat screen (after a user registered and logged in).
I want it to look like a normal chat app, so the last message should be at the bottom of the screen. I even reversed the data and list view, but it didn't work.
My code:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:naber/constants.dart';
final _firestore=FirebaseFirestore.instance;
User loggedInUser;
class ChatScreen extends StatefulWidget {
static String id="chat_screen";
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final messageTextController = TextEditingController();
final _auth = FirebaseAuth.instance;
String messageText;
void initState(){
super.initState();
getCurrentUser();
}
void getCurrentUser()async{
try{
final currentUser = await _auth.currentUser;
if(currentUser!=null){
loggedInUser=currentUser;
}
}
catch(e){
print(e);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: null,
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
_auth.signOut();
Navigator.pop(context);
}),
],
title: Text('Chat'),
backgroundColor: Colors.lightBlueAccent,
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
MessagesStream(),
Container(
decoration: kMessageContainerDecoration,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: messageTextController,
onChanged: (value) {
messageText = value;
},
decoration: kMessageTextFieldDecoration,
),
),
FlatButton(
onPressed: () {
messageTextController.clear();
_firestore.collection('messages').add({
'text': messageText,
'sender': loggedInUser.email,
});
},
child: Text(
'Send',
style: kSendButtonTextStyle,
),
),
],
),
),
],
),
),
);
}
}
class MessagesStream extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('messages').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.lightBlueAccent,
),
);
}
final messages = snapshot.data.docs.reversed;
List<MessageBubble> messageBubbles = [];
for (var message in messages) {
final messageText = message.data()['text'];
final messageSender = message.data()['sender'];
final currentUser = loggedInUser.email;
final messageBubble = MessageBubble(
sender: messageSender,
text: messageText,
isMe: currentUser == messageSender,
);
messageBubbles.add(messageBubble);
}
return Expanded(
child: ListView(
reverse: true,
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
children: messageBubbles,
),
);
},
);
}
}
class MessageBubble extends StatelessWidget {
MessageBubble({this.sender, this.text, this.isMe});
final String sender;
final String text;
final bool isMe;
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment:
isMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: <Widget>[
Text(
sender,
style: TextStyle(
fontSize: 12.0,
color: Colors.black54,
),
),
Material(
borderRadius: isMe
? BorderRadius.only(
topLeft: Radius.circular(30.0),
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0))
: BorderRadius.only(
bottomLeft: Radius.circular(30.0),
bottomRight: Radius.circular(30.0),
topRight: Radius.circular(30.0),
),
elevation: 5.0,
color: isMe ? Colors.lightBlueAccent : Colors.white,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
child: Text(
text,
style: TextStyle(
color: isMe ? Colors.white : Colors.black54,
fontSize: 15.0,
),
),
),
),
],
),
);
}
}
You add messages with:
_firestore.collection('messages').add({
'text': messageText,
'sender': loggedInUser.email,
});
Firestore doesn't have any built-in default ordering for documents. If you want to be able to order the documents, you will need to add a value to each document to allow that.
For example, you could add a timestamp of when the document was created with:
_firestore.collection('messages').add({
'text': messageText,
'sender': loggedInUser.email,
'createdAt': FieldValue.serverTimestamp()
});
By using FieldValue.serverTimestamp() the server will automatically populate this field, which you can then use when reading the data with:
stream: _firestore.collection('messages').orderBy('createdAt', descending: true).snapshots()
Im calling a Firebase user email, i want to display user details on the screen. When widget loads, NoSuchMethod error displays and crashes app. Not sure where to go from here
import 'package:flutter/material.dart';
import 'package:simmanager/constaints.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class SettingScreen extends StatefulWidget {
#override
_SettingScreenState createState() => _SettingScreenState();
}
class _SettingScreenState extends State<SettingScreen> {
final _auth = FirebaseAuth.instance;
final _firestore = Firestore.instance;
FirebaseUser loggedInUser;
#override
void initState() {
getCurrentUser();
super.initState();
}
void getCurrentUser() async {
try {
final user = await _auth.currentUser();
if (user != null) {
loggedInUser = user;
}
} catch (e) {
print(e);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Settings'),
backgroundColor: primaryColor,
),
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Icon(
Icons.edit,
color: Colors.black,
),
backgroundColor: secondaryColor,
),
body: SafeArea(
child: Container(
color: backgroundColor,
child: Column(
children: <Widget>[
Center(
child: Container(
margin: EdgeInsets.only(top: 20.0),
child: Icon(
Icons.account_circle,
size: 75.0,
color: primaryLight,
),
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
blurRadius: 5.0,
color: Colors.grey[300],
spreadRadius: 5.0,
),
],
borderRadius: BorderRadius.circular(20.0),
),
padding: EdgeInsets.all(25.0),
child: Row(
children: <Widget>[
Container(
child: Text(
'Name: ',
style: TextStyle(fontSize: 16.0),
),
),
// TODO: add stream for user details
Container(
child: Text('Test'),
),
],
),
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
blurRadius: 5.0,
color: Colors.grey[300],
spreadRadius: 5.0,
),
],
borderRadius: BorderRadius.circular(20.0),
),
padding: EdgeInsets.all(25.0),
child: Row(
children: <Widget>[
Container(
child: Text(
'Email: ',
style: TextStyle(fontSize: 16.0),
),
),
// TODO: add stream for user details
Container(
child: Text(loggedInUser.email),
),
],
),
),
),
The following NoSuchMethodError was thrown building SettingScreen(dirty, state: _SettingScreenState#b9d92):
The getter 'email' was called on null.
Receiver: null
Tried calling: email
I've passed through it too. The way I managed so that I could fix the error was change the position of auth.currentUser() declaration. You probably have created your Auth auth inside the StatelessWidget.
Try to move the instance of Auth from StatelessWidget to your State, right before your void initState().