I updated to cloud_firestore 0.14.0
There's a few break changes:
BREAKING: The get data getter is now a data() method instead.
Before the update this is how I used the getter data
Before:
Future<String> getUsernameFromUserId(String userId) async {
return (await _userFirestoreCollection.document(userId).get()).data['screenName'];
}
This is how I use data now.. But doesn't seem to be working...
Now:
Future<String> getUsernameFromUserId(String userId) async {
return (await _userFirestoreCollection.document(userId).get()).data()['screenName'];
}
Starting from version cloud_firestore 0.14.0:
The method document() was changed and now you have to use doc() instead, therefore in your code you have to do the following:
Future<String> getUsernameFromUserId(String userId) async {
return (await _userFirestoreCollection.doc(userId).get()).data()["screenName"];
}
Example:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: FirstRoute(title: 'First Route'),
);
}
}
class FirstRoute extends StatefulWidget {
FirstRoute({Key key, this.title}) : super(key: key);
final String title;
#override
_FirstRouteState createState() => _FirstRouteState();
}
class _FirstRouteState extends State<FirstRoute> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("test"),
),
body: FutureBuilder(
future: getData(),
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Column(
children: [
Container(
height: 27,
child: Text(
"Name: ${snapshot.data.data()['name']}",
overflow: TextOverflow.fade,
style: TextStyle(fontSize: 20),
),
),
],
);
} else if (snapshot.connectionState == ConnectionState.none) {
return Text("No data");
}
return CircularProgressIndicator();
},
));
}
Future<DocumentSnapshot> getData() async {
await Firebase.initializeApp();
return await FirebaseFirestore.instance
.collection("users")
.doc("docID")
.get();
}
}
Related
On Flutter Web, the userChanges stream from a FirebaseAuth instance never emits the signed in user after a page reload. Instead, it only emits null. With the example below, the app gets stuck on the loading page.
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(App());
}
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/loading',
onGenerateRoute: (settings) {
switch (settings.name) {
case '/error':
return MaterialPageRoute(builder: (_) => ErrorScreen());
case '/loading':
return MaterialPageRoute(builder: (_) => LoadingScreen());
case '/signin':
return MaterialPageRoute(builder: (_) => SignInScreen());
case '/welcome':
return MaterialPageRoute(builder: (_) => WelcomeScreen());
default:
return MaterialPageRoute(
builder: (_) => Center(child: Text('Unknown route')));
}
},
);
}
}
class ErrorScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Center(
child: Text('An error occurred.'),
),
);
}
}
class LoadingScreen extends StatefulWidget {
#override
_LoadingScreenState createState() => _LoadingScreenState();
}
class _LoadingScreenState extends State<LoadingScreen> {
#override
void initState() {
init();
super.initState();
}
init() async {
try {
await Firebase.initializeApp();
if (kDebugMode) {
await FirebaseAuth.instance.useEmulator('http://localhost:1001');
}
final preferences = await SharedPreferences.getInstance();
bool signedIn = preferences.getBool('IS_SIGNED_IN') ?? false;
String landingPath = '/signin';
if (signedIn) {
landingPath = '/welcome';
// Wait for the userChanges to emit a non-null element.
await FirebaseAuth.instance
.userChanges()
.firstWhere((user) => user != null);
}
Navigator.of(context).pushReplacementNamed(landingPath);
} catch (error) {
print(error);
Navigator.of(context).pushReplacementNamed('/error');
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Center(
child: Text('Loading...'),
),
);
}
}
class SignInScreen extends StatelessWidget {
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
TextField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email address'),
),
TextField(
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
controller: _passwordController,
),
ElevatedButton(
onPressed: () => _submit(context),
child: Text('SIGN IN'),
),
],
),
),
);
}
void _submit(BuildContext context) async {
final email = _emailController.text;
final password = _passwordController.text;
FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password)
.then((credential) async {
final preferences = await SharedPreferences.getInstance();
await preferences.setBool('IS_SIGNED_IN', true);
Navigator.of(context).pushReplacementNamed('/welcome');
});
}
}
class WelcomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
Text('Welcome!'),
ElevatedButton(
onPressed: () => _signOut(context),
child: Text('SIGN OUT'),
)
],
),
),
);
}
void _signOut(BuildContext context) {
FirebaseAuth.instance.signOut().then((_) async {
final preferences = await SharedPreferences.getInstance();
await preferences.setBool('IS_SIGNED_IN', false);
Navigator.of(context).pushReplacementNamed('/signin');
});
}
}
If it helps, I'm using version 8.3.0 of the Firebase Javascript libraries in my index.html file.
Am I missing something here?
It turns out the code above is fine. The issue is the emulator. Commenting out these lines of code makes the app behave as expected:
if (kDebugMode) {
FirebaseAuth.instance.useEmulator('http://localhost:1001');
}
I've filed a bug report on FlutterFire's repo about this emulator issue.
When I run the code below, all I am getting now is.
I copied this code from another this post. This seems to work, prior to the last code I had, but I still am getting no success on retrieving any data. I tried the other things in the same post but I had no luck.
The method 'data' was called on null.
Receiver: null
Tried calling: data()
void main() {
runApp(myApp());
}
class myApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: FirstRoute(title: 'First Route'),
);
}
}
class FirstRoute extends StatefulWidget {
FirstRoute({Key key, this.title}) : super(key: key);
final String title;
#override
_FirstRouteState createState() => _FirstRouteState();
}
class _FirstRouteState extends State<FirstRoute> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("test"),
),
body: FutureBuilder(
future: getData(),
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Column(
children: [
Container(
height: 27,
child: Text(
"Name: ${snapshot.data.data()['Name']}",
overflow: TextOverflow.fade,
style: TextStyle(fontSize: 20),
),
),
],
);
} else if (snapshot.connectionState == ConnectionState.none) {
return Text("No data");
}
return CircularProgressIndicator();
},
));
}
Future<DocumentSnapshot> getData() async {
await Firebase.initializeApp();
return await FirebaseFirestore.instance
.collection("test")
.doc()
.get();
}
}
On the firestore website it says that there are some reads and there's also snapshots listeners active, but the error still persists.
Any recommendations and tips would be great. Thanks!
[![enter image description here][1]][1]
I need to do it like this here:
[1]: https://i.stack.imgur.com/bNdZ3.png
But I can't do it. I tried some stuff but it doesn't work. Here is my main.dart below. I created the showImage method for showing image, I also applied it by Image.network(url); code but it didn't work,so I commented it.
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.red,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
var url;
void _incrementCounter() {
setState(() {
_counter++;
});
}
void showImage() async {
final ref = FirebaseStorage.instance.ref().child('erkekyuz');
// no need of the file extension, the name will do fine.
url = await ref.getDownloadURL();
print(url);
}
Widget _buildListItem(BuildContext context, DocumentSnapshot document) {
String mezunD;
if (document.data()['mezunDurumu'] == false) {
mezunD = "mezun değil";
}
if (document.data()['mezunDurumu'] == true) {
mezunD = "mezun değil";
}
var listTile = ListTile(
title: Column(
children: [
Expanded(
child: Text(
"Ad Soyad: " + document.data()['adSoyad'],
),
),
Expanded(
child: Text(
"Yaş: " + document.data()['yas'].toString(),
),
),
Expanded(
child: Text(
"Doğum Tarihi: " + document.data()['dogumTarihi'],
),
),
Expanded(
child: Text("Mezun Durumu: " + mezunD),
),
//Image.network(url),
//this didn't work somehow.
],
),
);
return listTile;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Öğrenci Durumu"),
),
body: StreamBuilder(
stream: FirebaseFirestore.instance.collection('tablolar').snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return const Text('Loading...');
return ListView.builder(
itemExtent: 100.0,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) =>
_buildListItem(context, snapshot.data.documents[index]),
);
}),
);
}
}
Is your url variable showing any value?
Call your showImage() method like this to load image.
#override
void initState() {
super.initState();
showImage();
}
for showing images you can use :https://pub.dev/packages/cached_network_image
I'm trying to play a video from a URL of a Firestore Document. To play a video in Flutter, I have to instantiate its Url in the init() method. I set a default URL to a butterfly video, and the value was supposed to be replaced by the URL obtained from Firestore. (So that it is easy for me to see if the code works). However, the code does not work properly. I got an error that says "NoSuchMethodError: The getter 'value' was called on null".
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// Create the initialization Future outside of build
final Future<FirebaseApp> _initialization = Firebase.initializeApp();
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: _initialization,
builder: (context, snapshot) {
// Check for error
if (snapshot.hasError) {
print(snapshot.error);
return Center(
child: Container(
child: Text(
"Something went wrong",
textDirection: TextDirection.ltr,
),
),
);
}
//Once complete, show your application
if (snapshot.connectionState == ConnectionState.done) {
return MaterialApp(
title: 'Flutter Demo',
home: VideoPlayerScreen(),
);
}
return CircularProgressIndicator();
});
}
}
class VideoPlayerScreen extends StatefulWidget {
#override
_VideoPlayerScreenState createState() => _VideoPlayerScreenState();
}
class _VideoPlayerScreenState extends State<VideoPlayerScreen> {
VideoPlayerController _controller;
Future<void> _initializeVideoPlayerFuture;
FirebaseFirestore firestore = FirebaseFirestore.instance;
String videoUrl =
'https://flutter.github.io/assets-for-api-docs/assets/videos/butterfly.mp4';
#override
void initState() {
firestore.collection("videos").get().then((QuerySnapshot querySnapshot) => {
querySnapshot.docs.forEach((doc) {
// _controller.dispose();
videoUrl = doc["videoUrl"];
_controller = VideoPlayerController.network(videoUrl);
_initializeVideoPlayerFuture = _controller.initialize();
print(videoUrl);
})
});
// _controller = VideoPlayerController.network(videoUrl);
// _initializeVideoPlayerFuture = _controller.initialize();
super.initState();
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Flutter Video Player"),
),
body: FutureBuilder(
future: _initializeVideoPlayerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Column(
children: [
AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
),
],
);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
if (_controller.value.isPlaying) {
_controller.pause();
} else {
_controller.play();
}
});
},
child: Icon(
_controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
),
),
);
}
}
Try the following:
#override
void initState() {
super.initState();
firestore.collection("videos").get().then((QuerySnapshot querySnapshot) => {
querySnapshot.docs.forEach((doc) {
videoUrl = doc["videoUrl"];
_controller = VideoPlayerController.network(videoUrl);
_initializeVideoPlayerFuture = _controller.initialize().then((_) {
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
setState(() {});
});
});
});
}
Since initialize() is asynchronous, then you can use the method then which will get called when the future completes. Inside the callback, you can call setState() which will trigger a rebuild and notify the framework that the internal state of the widgets has changed .
https://pub.dev/packages/video_player
I tried to implements this Authentification here Firebase with Porvider here the issue is I want to save the state of variable loggedIn even I close and reponning the app so I used this code but dont work
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Consumer<AuthenticationService>(builder: (_, auth, __) {
if (auth.getCurrentUser() != null)
return HomeView();
else
return TermsView();
});
}
}
here method to get current user
Future getCurrentUser() async {
FirebaseUser _user ;
_user = await FirebaseAuth.instance.currentUser();
return _user ;
}
Is there a way to check signing in inside Consumer?
You need to use FirebaseAuth.currentUser to check if user is signed in or not, I am using FutureBuilder inside Consumer for this work.
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(
ChangeNotifierProvider<Auth>(
create: (_) => Auth(),
child: MaterialApp(home: MyApp()),
),
);
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Consumer<Auth>(
builder: (_, auth, __) {
return FutureBuilder<FirebaseUser>(
future: auth.currentUser,
builder: (context, snapshot) {
if (snapshot.hasData) return HomeScreen();
return LoginScreen();
},
);
},
);
}
}
class HomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFF4C3E13),
appBar: AppBar(title: Text('Home Screen')),
floatingActionButton: FloatingActionButton.extended(
label: Text('Sign out'),
onPressed: () async {
final auth = Provider.of<Auth>(context, listen: false);
await auth.signOut();
},
),
);
}
}
class LoginScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Login Screen')),
body: Center(
child: RaisedButton(
onPressed: () async {
final auth = Provider.of<Auth>(context, listen: false);
await auth.signIn(email: 'user#user.com', password: 'user1234');
},
child: Text('Sign In'),
),
),
);
}
}
class Auth with ChangeNotifier {
final _auth = FirebaseAuth.instance;
Future<void> signOut() async {
await _auth.signOut();
notifyListeners();
}
Future<void> signIn({#required String email, #required String password}) async {
await _auth.signInWithEmailAndPassword(email: email, password: password);
notifyListeners();
}
Future<FirebaseUser> get currentUser async {
return await _auth.currentUser();
}
}