Abdullrahman Wasfi
Abdullrahman Wasfi

Reputation: 501

Use stream provider inside Stateful Widget to get data for single firestore document

I have specific firestore document and I want get the value of field of that document updated every second because the field represent the number of notifications of user, But when I Looking for stream provider first time I was read we can't use it inside Stateful widget.

My Document Path enter image description here

My home page code:

class Home extends StatefulWidget {
  final User me;

  Home({
    Key key,
    this.me,
  }) : super(key: key);

  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  final Firestore _firestore = Firestore.instance;
  int numberOfNotifications;
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: GlobalUniversal.whiteBG,
      body: Center(
        child: Text(numberOfNotifications.toString()),
      ),
    );
  }
}

db.dart

class DatabaseService {
  final Firestore db = Firestore.instance;

  Future<UserNotification> getUserNotification(String doc) async {
    var snap = await db.collection(NOTIFICATIONS_USERS_ONE_COLLECTION).document(doc).get();
    return UserNotification.fromMap(snap.data);
  }

  Stream<UserNotification> streamUserNotifications(String doc){
    return db.collection(NOTIFICATIONS_USERS_ONE_COLLECTION).document(doc).snapshots().map((snap) => UserNotification.fromMap(snap.data));
  }
}

user.dart

class UserNotification {
      int userNotifications;
      UserNotification({this.userNotifications});
    
      factory UserNotification.fromMap(Map data) {
        return UserNotification(
          userNotifications: data[UN_READ_COUNTS_FIELD] ?? 0,
        );
      }
    }

but when I try call provider inside home page I got an error. enter image description here

error: The named parameter 'stream' isn't defined. (undefined_named_parameter)

Upvotes: 0

Views: 684

Answers (1)

Valentin Vignal
Valentin Vignal

Reputation: 8240

Don't use the .value if you are instantiating your stream in your provider

StreamProvider<UserNofitication>(
  create: (BuildContext context) => db.streamUserNotification(widget.me.doc),
  child: Center(
    child: Text(numberOfNotifications.toString()),
  ),
),

If db.streamUserNotification(widget.me.doc) is already an instance of stream, you can use StreamProvider.value and the named parameter is value and not stream :

StreamProvider<UserNofitication>.value(
  value: db.streamUserNotification(widget.me.doc),
  child: Center(
    child: Text(numberOfNotifications.toString()),
  ),
),

EDIT

to use the stream you can use the builder of the StreamProvider to read the context

StreamProvider<UserNofitication>(
  create: (BuildContext context) => db.streamUserNotification(widget.me.doc),
  builder: (BuildContext context, Widget child) {
    numberOfNotifications = context.watch<UserNotification>()?.userNotifications ?? 0;
    return Center(
      child: Text(numberOfNotifications.toString()),
    );
  },
),

Upvotes: 1

Related Questions