Why im getting provider error in project? - firebase

Im getting this error when im trying to use provider in my code .
IN new in flutter and a beginner so maybe anyone can explain how to fix I search already but still cannot find something.
The following ProviderNotFoundException was thrown building MeinAccount(dirty, state: _MeinAccountState#e2cbb):
Error: Could not find the correct Provider<User> above this MeinAccount Widget
This happens because you used a `BuildContext` that does not include the provider
of your choice. There are a few common scenarios:
- You added a new provider in your `main.dart` and performed a hot-reload.
To fix, perform a hot-restart.
- The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then
other routes will not be able to access that provider.
- You used a `BuildContext` that is an ancestor of the provider you are trying to read.
Make sure that MeinAccount is under your MultiProvider/Provider<User>.
This usually happens when you are creating a provider and trying to read it immediately.
For example, instead of:
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// Will throw a ProviderNotFoundError, because `context` is associated
// to the widget that is the parent of `Provider<Example>`
child: Text(context.watch<Example>()),
),
}
consider using `builder` like so:
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// we use `builder` to obtain a new `BuildContext` that has access to the provider
builder: (context) {
// No longer throws
return Text(context.watch<Example>()),
}
),
}
If none of these solutions work, consider asking for help on StackOverflow:
https://stackoverflow.com/questions/tagged/flutter
The relevant error-causing widget was:
MeinAccount file:///Users/myname/StudioProjects/projectname/lib/main.dart:48:41
When the exception was thrown, this was the stack:
#0 Provider._inheritedElementOf (package:provider/src/provider.dart:332:7)
#1 Provider.of (package:provider/src/provider.dart:284:30)
#2 _MeinAccountState.build (package:projectname/seitenleiste/meinacount.dart:362:27)
#3 StatefulElement.build (package:flutter/src/widgets/framework.dart:4704:27)
#4 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4587:15)
This is my widget UPDATEEE:
Widget _buildPasswordTF() {
final user = Provider.of<User>(context);
return StreamBuilder<UserData>(
stream: DatbaseService(uid:user.uid).userData,
builder: (context, snapshot) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Password',
Maybe anyone can help :
Also here's my main dart UPDATEEE:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context){
return MultiProvider(
providers: [
//DatbaseService(create: (_) => User()), // add your providers like this.
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title:'Appbar Scaffold',
theme: ThemeData(
scaffoldBackgroundColor: Colors.white,
primaryColor: Colors.white,
If you need more informations please add a comment. Thanks again.

It's because you haven't registered your provider. You need to register them, before consuming them. Wrap your MaterialApp widget with MultiProvider (if you have multiple providers in your app).
example:
child: MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => User()), // add your providers like this.
],
child:MaterialApp(..........)
);

Related

Bloc isn't found in the widget tree

Because the code is to big I will try and sum it up in words.
This is the latest exception:
Error: Could not find the correct Provider<ProdEntriesSearchCubit> above this BlocListener<ProdEntriesSearchCubit, ProdEntriesSearchState> Widget
This likely happens because you used a `BuildContext` that does not include the provider
of your choice. There are a few common scenarios:
- The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then
other routes will not be able to access that provider.
- You used a `BuildContext` that is an ancestor of the provider you are trying to read.
Make sure that BlocListener<ProdEntriesSearchCubit, ProdEntriesSearchState> is under your MultiProvider/Provider<ProdEntriesSearchCubit>.
This usually happens when you are creating a provider and trying to read it immediately.
In screen 1 I have the following build method:
Widget build(BuildContext context) {
final entriesState = context.watch<ProdEntriesCubit>().state;
return BlocProvider(
create: (context) => ProdEntriesSearchCubit(
productsRepository: context.watch<ProductsRepository>(),
),
child: Builder(
builder: (context) => SafeScreen(
child: Scaffold(
body: _buildBody(context, entriesState: entriesState),
floatingActionButton: _buildFab(context),
),
),
),
);
}
_buildFab(BuildContext context) {
return FloatingActionButton(
child: Icon(
Icons.add,
color: Colors.white,
),
onPressed: () async {
await navigatorPush(context, screen: AdminProdEntryScreen());
},
);
}
In AdminProdEntryScreen I do again:
navigatorPush(
context,
screen: EntryProdSearchScreen(),
);
In EntryProdSearchScreen I get the error from above.
Why is the BloC/Cubit not found in the widget tree?
I even used multiple Builder widgets but I am always hit by this exception.
When you provide your BLoC, it has access to the current widget tree, when you navigate to another screen it won't have access to that BLoC.
You can solve this in one of two ways.
1
You wrap your whole app with a bloc (Multi) provider that you can access the bloc no matter the navigation.
The reason that this works is because you are wrapping your navigation within MaterialApp with the bloc provider.
runApp(
MultiBlocProvider(
providers: [
BlocProvider<ProdEntriesSearchCubit>(
create: (context) => ProdEntriesSearchCubit(),
),
],
child: MyApp(),
),
);
2
You can pass an instance of the bloc through the nav route and use BlocProvider.value to provide the same instance of the bloc.
//nav method
Navigator.of(context).pushNamed(
'/entry_prod_search_screen',
arguments: context.read< ProdEntriesSearchCubit >(),
);
//in the navigated route screen
final bloc = ModalRoute.of(context).settings.arguments;
return MultiBlocProvider(
providers: [
BlocProvider.value(
value: bloc,
),
],
child: ...,
);

Struggling to load images from Firebase Firestore into ListItem in Flutter app

I am having a bit of issue loading images from my Firebase Firestore database into my Flutter app. I am sort of stuck on this since I don't know what to do currently. I have seen a way to use NetworkImage to download an image on a list tile but it only does one image. I am trying to figure out a way to use a separate image for each item in the Firestore database.
I have hooked up the image URL from the Firebase Storage to Firestore under the imageURL key which is a String. But I am still struggling to figure out how to do this. I have also downloaded all the dependencies such as Firebase and Firestore. If anyone does offer to help or shares a tip on how they have worked with something similar to this, it'd be greatly appreciated! :)
class HomeTab extends StatefulWidget {
#override
_HomeTabState createState() => _HomeTabState();
}
class _HomeTabState extends State<HomeTab> {
#override
Widget build(BuildContext context) {
// This will reference our posts collection in Firebase Firestore NoSQL database.
CollectionReference posts = FirebaseFirestore.instance.collection('posts');
return Center(
child: Container(
width: 250,
child: StreamBuilder<QuerySnapshot>(
// Renders every post from the Firebase Firestore Database.
stream: posts.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return new ListView(
children: snapshot.data.docs.map((DocumentSnapshot document) {
return Card(
margin: EdgeInsets.all(20.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
elevation: 10,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
// Renders the title on every single listview.
title: new Text(document.data()['title']),
// leading: new NetworkImage(''),
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => ReaderPage(),
),
);
},
),
],
// Added Column
// In case if things don't work, go back to this.
// child: new ListTile(
// title: new Text(document.data()['text']),
// ),
),
);
}).toList(),
);
},
),
),
);
}
}
Here is my Firebase Storage
My Firestore database
The NetworkImage class is not a flutter widget class. It is responsible for downloading the image from the URL provided. It inherits from the ImageProvider class.
From the flutter docs:
Fetches the given URL from the network, associating it with the given scale.
Use Image.network for a shorthand of an Image widget backed by NetworkImage.
You should be using the Image.network named constructor of the Image widget to create a flutter widget used to display image with help of NetworkImage.
You should replace the NetworkImage in your widget tree with:
new Image.network("https://i.stack.imgur.com/W98kA.png")

How to instantiate a Moor_Flutter databse (daos) with provider in main page?

This happens when instantiating the NotificationsPage routed from the MyHomePage()
Here is my code :
void main() =>runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
final db = AppDatabase();
return MultiProvider(
providers: [
// ignore: unnecessary_statements, missing_return
Provider<MeetingDao>( create: (BuildContext context) {builder: (_) => db.Table1Dao;}, ),
// ignore: unnecessary_statements, missing_return
Provider<UserDao>( create: (BuildContext context) {builder: (_) => db.Table2Dao;}, ),
],
child: MaterialApp(
title: 'MyApp',
home: MyHomePage(),
),
);
}
}
Here is the error log:
Error: Could not find the correct Provider above this NotificationsPage Widget
This likely happens because you used a BuildContext that does not include the provider
of your choice. There are a few common scenarios:
The provider you are trying to read is in a different route.
Providers are "scoped". So if you insert of provider inside a route, then
other routes will not be able to access that provider.
You used a BuildContext that is an ancestor of the provider you are trying to read.
Make sure that NotificationsPage is under your MultiProvider/Provider.
This usually happen when you are creating a provider and trying to read it immediatly.
For example, instead of:
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// Will throw a ProviderNotFoundError, because `context` is associated
// to the widget that is the parent of `Provider<Example>`
child: Text(context.watch<Example>()),
),
}
consider using builder like so:
Widget build(BuildContext context) {
return Provider<Example>(
create: (_) => Example(),
// we use `builder` to obtain a new `BuildContext` that has access to the provider
builder: (context) {
// No longer throws
return Text(context.watch<Example>()),
}
),
}
Any suggestion on whats wrong with this main page ? in the Notifications Page I am accessing it like
final tbl1Dao = Provider.of<Table1Dao>(context,listen: false);

How To Make Streams in flutter dart work with provider

This was working initially and it just stopped and I cannot figure out where the problem lies.
I am working with streams on my flutter project in provider package. Streams are being emitted from services files and listening is happening on the widgets file. Firebase onAuthStateChanged stream is working but mine are not working.
I have alot of code in my files so am not going to post everything here.
I have a problem with AuthStatus stream
I tried subscribing to the stream on the widget class but it seems like no streams are getting emitted
MyApp(){
auth.authStateStream.listen((d){print("$d is data");});
}
This how firebase streams are getting emiited from services file
Stream<UserModel> get onAuthStateChanged{
return _firebaseAuth.onAuthStateChanged.map(_userFromFirebase);
}
I have a problem with AuthStatus stream. This was working initially
This is how AuthStatus stream is getting emmited from services file
//Services file
final StreamController<AuthStatus> _currentAuthStateController =
StreamController<AuthStatus>.broadcast();
Stream<AuthStatus> get authStateStream{
return _currentAuthStateController.stream;
}
void testStremas() {
//Stoast.setMessage("Test Message");
_currentAuthStateController.add(AuthStatus.ACTIVE);
}
This is how provider is litening to streams as a parent of the MaterialAPP widget
class MyApp extends StatelessWidget {
//I was trying if i my widget could subscribe to the stream
MyApp (){
auth.authStateStream.listen((d){print("$d is data");});
}
final ToastHelper toast = ToastHelper();
final ThemeHelper theme = ThemeHelper();
final AuthService auth = AuthService();
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
StreamProvider<UserModel>.value(value: auth.onAuthStateChanged),
StreamProvider<ToastMessage>.value(value: toast.onNewMessage),
StreamProvider<AuthStatus>.value(
value: auth.authStateStream, initialData: AuthStatus.NONE),
],
child: MaterialApp(
title: Strings.appName,
theme: theme.darkThemeData(),
home: Loader(),
routes: {
'home': (context) => Home(),
},
debugShowCheckedModeBanner: false,
),
);
}
}
This is how the above method is getting called on a the widget on a click of a button
//Widgets file
onTap: () => auth.testStremas(),
The expected result should be when the AuthStatus change from the services file, The widgets should be notified via the provider package. Thanks in advance
Widget _body(BuildContext context) {
final AuthStatus _authStatus = Provider.of<AuthStatus>(context);
return Center(
child: Container(
constraints: BoxConstraints(maxWidth: 300),
child: SingleChildScrollView(
child: Center(
child: _authStatus == AuthStatus.ACTIVE
? Padding(
padding: const EdgeInsets.all(8.0),
child:CircularProgressIndicator(strokeWidth: 2,)
)
: _buildScreen(context),
)),
),
);
}
I'm not sure - try to change
final StreamController<AuthStatus> _currentAuthStateController =
StreamController<AuthStatus>.broadcast();
to
final StreamController<AuthStatus> _currentAuthStateController =
BehaviorSubject<AuthStatus>();
This BehaviorSubject from rxdart library https://pub.dev/packages/rxdart, so, you should import it. BehaviorSubject is keep last state of stream. You can read more here https://pub.dev/documentation/rxdart/latest/rx/BehaviorSubject-class.html
import 'package:rxdart/rxdart.dart';

Flutter: multiple firebase projects in one app but showing incorrect data

The last few days I spend a lot of time to read through several SO-questions and tutorials. What I'm trying to achieve is, that a user of my flutter app can choose a firebase project and log in with email/password. After the login, obviously, the correct data of the corresponding database should be shown. And that is where I fail.
After a while of reading some sites and questions from SO, I went with the following site to get the first part of the login.
https://firebase.googleblog.com/2016/12/working-with-multiple-firebase-projects-in-an-android-app.html
After working through this article, I was able to successfully log in to my defined firebase projects.
How did I know that the login was successful? I compared the user-uids from the projects with the print statement from my app in the console. That was the prove my configuration for the non-default project is correct.
But now the main problem which I can't solve.
After the login, the data is always of the default firebase project from the google-service.json.
For state management, I choose the provider package, as they mentioned in the I/O '19. So inside my main.dart, I wrap the whole application with MultipleProvider:
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<LoginModel>(
builder: (_) => LoginModel(),
),
ChangeNotifierProvider<Auth>(
builder: (_) => Auth(),
),
],
child: MaterialApp(
title: 'Breaking News Tool',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: RootPage(),
),
);
}
The provided Auth class is a service that connects to firebase sdk and also configure non-default apps to create the needed firebase auth
abstract class BaseAuth {
getDefaultAuth();
getAbnAuth();
...
}
class Auth with ChangeNotifier implements BaseAuth {
...
Auth() {
_configureAbnApp();
_configureProdApp();
}
getDefaultAuth() {
_firebaseAuth = FirebaseAuth.instance;
}
getAbnAuth() {
_firebaseAuth = FirebaseAuth.fromApp(_abnApp);
}
_configureAbnApp() {
FirebaseOptions abnOptions = FirebaseOptions(
databaseURL: 'https://[project-id].firebaseio.com',
apiKey: 'AIzaSxxxxxxxxxxxxxxxx,
googleAppID: '1:10591xxxxxxxxxxxxxxxxxxx');
FirebaseApp.configure(name: 'abn_database', options: abnOptions)
.then((result) {
_abnApp = result;
});
}
...
}
After a log in the app redirects the user to the home_page (StatefulWidget). Here I use a snapshot of the database to show data.
_stream = Firestore.instance.collection(collection).snapshots();
...
Center(
child: Container(
padding: const EdgeInsets.all(10.0),
child: StreamBuilder<QuerySnapshot>(
stream: _stream,
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Text('Loading...');
default:
return ListView(
children: snapshot.data.documents
.map((DocumentSnapshot document) {
return CustomCard(
docID: document.documentID,
title: document[title],
message: document[message],
fromDate: document[fromDate],
endDate: document[endDate],
disableApp: document[disableApp],
);
}).toList(),
);
}
},
),
),
),
In the beginning, I only had one project to connect to and the data was correct. But now I successfully connect to another project with the correct user-uid, but the data is always from the default project which is defined by the google-service.json.
And at this point, I have no clue why this happens.
Did anyone have an advice or idea?
You create your _stream based on Firestore.instance, which will give you the default firebase app, as documented in the docs:
/// Gets the instance of Firestore for the default Firebase app.
static Firestore get instance => Firestore();
Therefore you always get the data from the default project.
To fix this you need to create your firestore using the app created by FirebaseApp.configure().
So replace:
_stream = Firestore.instance.collection(collection).snapshots();
with
_stream = Firestore(app: _abnApp).collection(collection).snapshots();

Resources