Reputation: 1
I want to write the data to the fire store database.
I wrote the code in this way in subscriptions class:
import 'package:flutter/material.dart';
import 'package:flutterapptest/services/database.dart';
import 'package:provider/provider.dart';
class Subscriptions extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Subscribed'),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => _addTrack(context),
),
);
}
Future<void> _addTrack(BuildContext context) async {
final database = Provider.of<Database>(context, listen: false);
await database.addTrack({
'name': 'Track',
'time': 20,
});
}
}
in the database class ......
import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:meta/meta.dart';
abstract class Database {
Future<void> addTrack(Map<String, dynamic> trackData);
}
class FirestoreDatabase implements Database {
FirestoreDatabase({@required this.uid}) : assert(uid != null);
final String uid;
Future<void> addTrack(Map<String, dynamic> trackData) async{
final path = '/users/$uid/track/track_abc';
final documentReference = Firestore.instance.document(path);
await documentReference.setData(trackData);
}
}
for this i am getting the error:
could not find the correct
Provider<Database>
above the subscriptions widget
For this a friend suggested me to do:
If you push the
Subscriptions
widget inside a route, it won't have access toProvider.of<Database>.
The quickest solution is to pass
Database
as a constructor argument to theSubscriptions
class, and use that as an instance variable rather than withProvider.of<Database>
Can anyone please help me what should i do now? I am new to flutter.
Upvotes: 0
Views: 364
Reputation: 741
This is how I would do it. I know this includes much more then just the addTrack function but I guess you also need a global state somewhen and a changeNotifier, otherwise it makes no sense to use the provider.
First create the service:
import 'package:cloud_firestore/cloud_firestore.dart';
final CollectionReference firestoreUsers =
Firestore.instance.collection('users');
class UserService {
static Future<Stream<Map<String, dynamic>>> streamTrack(String userId) async {
Stream<DocumentSnapshot> query =
await firestoreUsers.document('pathToListen...').snapshots();
return query.map((doc) => Map.from(doc.data));
}
static addTrack(String userId, Map<String, dynamic> trackData) async {
await firestoreUsers
.document(userId)
.collection('track')
.document('track_abc')
.setData(trackData);
}
}
Then the provider which holds the global state and uses the changeNotifier. These are just placeholders. Put there whatever you want to listen in the database.
import 'dart:async';
import 'package:flutter/material.dart';
import '../models_services/user_services.dart';
class UserProvider with ChangeNotifier {
// your global state, if you want to listen for data from database
StreamSubscription<Map<String, dynamic>> trackStream;
Map<String, dynamic> _streamedTrack;
Map<String, dynamic> get streamedTrack => _streamedTrack;
Future streamCurrentTrack(uid) async {
if(trackStream != null) {
trackStream.cancel();
}
Stream<Map<String, dynamic>> res = await UserService.streamTrack(uid);
trackStream = res.listen((track) {
_streamedTrack = track;
notifyListeners();
});
}
Future<void> addTrack(Map<String, dynamic> trackData) async {
// not sure what this is doing, i guess uid is null here...
FirestoreDatabase({@required this.uid}) : assert(uid != null);
final String uid;
await UserService.addTrack(uid, trackData);
}
}
Use the provider with changeNotifier in your code:
import 'package:flutter/material.dart';
import 'package:flutterapptest/provider/user_provider.dart';
import 'package:provider/provider.dart';
class Home extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => UserProvider()),
...
],
child: MaterialApp(
home: Scaffold(body: Subscriptions()
)));
}
}
class Subscriptions extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Subscribed'),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => _addTrack(context),
),
);
}
Future<void> _addTrack(BuildContext context) async {
final database = Provider.of<UserProvider>(context, listen: false);
await database.addTrack({
'name': 'Track',
'time': 20,
});
}
}
Upvotes: 1