简体   繁体   English

将用户 uid 传递给 Firestore ZF7B44CFFAFD5C52223D5498196C8A2E7BZ 查询 Flutter

[英]Pass user uid to Firestore stream query in Flutter

  1. Here I am using provider in main.dart to stream "itemsInUserDocument" data from a document.在这里,我在 main.dart 到 stream “itemsInUserDocument”数据中使用来自文档的提供程序。

Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
          StreamProvider<DocumentSnapshot>.value(
          value: DatabaseService().itemsInUserDocument,      <--- (1) Providing here
          ),
          StreamProvider<User>.value(
          value: AuthProvider().user,
          ),
      ],

  1. My problem is passing the userUID to the Stream query here.我的问题是在此处将 userUID 传递给 Stream 查询。 My document id's on Firestore is my userUID.我在 Firestore 上的文档 ID 是我的用户 UID。

final userUID = "3SlUigYBgsNgzjU8a9GSimhAhuu1";            <-- (2) Need to pass to stream "userID' below??


class DatabaseService {

  Stream<DocumentSnapshot> get itemsInUserDocument {

    final DocumentReference userData = Firestore.instance.collection('userdata').document(userUID);

    return userData.snapshots();
  }
}

  1. Here I am using the list in down the widget tree.在这里,我正在使用小部件树中的列表。
  @override
  Widget build(BuildContext context) {
    final userTaskDone = Provider.of<DocumentSnapshot>(context);

    List taskList = [];    <-- (3) Using the list here. 

    taskList = userTaskDone['tasks'].toList();

    print(taskList);


  • It currently works and I am getting the streamed data in section (3) as is now, but I need to pass the Firebase user UID into the stream in section (2).它目前有效,我现在在第 (3) 节中获取流数据,但我需要将 Firebase 用户 UID 传递到第 (2) 节中的 stream 中。

  • I can get the user UID in a stateful widget with setState function but everything I have tried doesn't work or seems like I am duplicating things too much, I am trying to use Provider to manage state properly.我可以使用 setState function 在有状态小部件中获取用户 UID,但我尝试过的一切都不起作用或者似乎我重复了太多东西,我正在尝试使用 Provider 来正确管理 state。

  • I can get the userUID with provider as well, but you can only use it on a (context), where my notifier section (2) is only a class.我也可以通过提供者获取 userUID,但您只能在(上下文)上使用它,其中我的通知程序部分 (2) 只是 class。

  • PLEASE help me with a solution.请帮助我解决问题。

EDIT:编辑:

I have tried the edits and the result is as follow:我已经尝试了编辑,结果如下:

Getting this critical error from provider when I enter the screen where it used to work before these changes to main.dart.当我进入在这些更改为 main.dart 之前它曾经工作的屏幕时,从提供者那里收到这个严重错误。

在此处输入图像描述

Here is the full code for main.dart with edits as it is now:以下是 main.dart 的完整代码,现在进行了编辑:

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData.dark(),
      title: 'Sendr',
      home: MainScreen(),
      routes: {
        SplashPage.id: (context) => SplashPage(),
        LoginScreen.id: (context) => LoginScreen(),
        NavigatorScreen.id: (context) => NavigatorScreen(),
        CragSelectionScreen.id: (context) => CragSelectionScreen(),
        CragRoutesScreen.id: (context) => CragRoutesScreen(),
        RouteDetailScreen.id: (context) => RouteDetailScreen(),
        MapScreen.id: (context) => MapScreen(),
      },
    );
  }
}

///Authentication Logic
class MainScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamProvider<User>.value(
      value: AuthProvider().user,
      child: Consumer<User>(
        builder: (context, user, __) {
          if (user == null) {
            return LoginScreen();
          } else {
            return MultiProvider(
              providers: [
                Provider<DatabaseService>.value(
                  value: DatabaseService(user.uid),
                ),
              ],
              child: NavigatorScreen(),
            );
          }
        },
      ),
    );
  }
}

This is my Database Service:这是我的数据库服务:

import 'package:cloud_firestore/cloud_firestore.dart';

class DatabaseService {
  DatabaseService(this.uid);

  final String uid;

  Stream<DocumentSnapshot> get itemsInUserDocument {
    final DocumentReference userData =
        Firestore.instance.collection('userdata').document(uid);
    return userData.snapshots();
  }
}

I have made no change to my step (3) where I am using it, is this where my problem might be now?我没有对我正在使用它的步骤 (3) 进行任何更改,这可能是我现在的问题吗?

I am trying to do more research on this.我正在尝试对此进行更多研究。 Working through the provider docs.通过提供者文档工作。 If I understand your suggestion correctly, we are streaming the User value from AuthProvider at the top, then consume the User value just below it then passing the user.uid value to the DatabaseService, which is used down the widget tree again.如果我正确理解您的建议,我们将从顶部的 AuthProvider 流式传输 User 值,然后使用其下方的 User 值,然后将 user.uid 值传递给 DatabaseService,该值再次在小部件树下使用。 Looks like I am almost there from your help.在你的帮助下,看起来我快到了。 If you don't mind, please let me know what you think of the provider error on the screen.如果您不介意,请告诉我您对屏幕上的提供程序错误的看法。 Much appreciated.非常感激。

You could try a switchmap from rxdart which listens to and maps a stream T to one of S .您可以尝试来自switchmaprxdart ,它侦听 stream T并将其映射到S之一。

Stream<S> switchMap<S>(Stream<S> Function(T value) mapper) =>
      transform(SwitchMapStreamTransformer<T, S>(mapper));
import 'package:rxdart/transformers.dart';

final userStream = AuthProvider().user;

final itemsStream = userStream.switchMap<DocumentSnapshot>(
  (user) {
    if (user == null) return Stream<DocumentSnapshot>.value(null);

    return itemsCollection.where('uid', isEqualTo: user.uid).snapshots();
  },
);
StreamProvider<DocumentSnapshot>.value(
  value: itemsStream,
),

Writing this off the cuff so it might be wrong.把它写在袖口上,所以它可能是错误的。

Edit编辑

Another way would just be to place your items provider one level below your user.另一种方法是将您的项目提供者置于用户之下一级。 That way you can just regularly consume the user uid value.这样您就可以定期使用用户 uid 值。

return StreamProvider<User>.value(
  value: AuthProvider().user,
  child: Consumer<User>(
    builder: (_, user, __) {
      if (!user) {
        // Not logged in
      } else {
        return MultiProvider(
          providers: [
            Provider.value<DatabaseService>(
              value: DatabaseService(user.uid),
            ),
            // More services that rely on user.uid
          ],
          child: SizedBox(),
        );
      }
    },
  ),
);

2 Edit 2 编辑

class DatabaseService {
  DatabaseService(this.uid);

  final String uid;

  getData() {
    return MyCollection.where('uid', isEqualTo: uid).snapshots();
  }
}

This seems to have worked having main.dart looking as below:这似乎有 main.dart 如下所示:

Main.dart主.dart


void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamProvider<User>.value(
      value: AuthProvider().user,
      child: Consumer<User>(
        builder: (context, user, __) {
          if (user == null) {
            return MaterialApp(
              debugShowCheckedModeBanner: false,
              theme: ThemeData.dark(),
              title: 'Sendr',
              home: LoginScreen(),
            );
          } else {
            return MultiProvider(
              providers: [
                StreamProvider<DocumentSnapshot>.value(
                  value: DatabaseService(user.uid).userRoutesDone,
                ),
              ],
              child: MaterialApp(
                debugShowCheckedModeBanner: false,
                theme: ThemeData.dark(),
                title: 'Sendr',
                home: NavigatorScreen(),
                routes: {
                  SplashPage.id: (context) => SplashPage(),
                  LoginScreen.id: (context) => LoginScreen(),
                  NavigatorScreen.id: (context) => NavigatorScreen(),
                  MapScreen.id: (context) => MapScreen(),
                },
              ),
            );
          }
        },
      ),
    );

My Notifier:我的通知者:

import 'package:cloud_firestore/cloud_firestore.dart';

class DatabaseService {
  DatabaseService(this.uid);

  final String uid;

  Stream<DocumentSnapshot> get itemsInUserDocument {
    final DocumentReference userData =
        Firestore.instance.collection('userdata').document(uid);
    return userData.snapshots();
  }
}

Where I used it down the widget tree:我在小部件树中使用它的地方:


  @override
  Widget build(BuildContext context) {
    final userTaskDone = Provider.of<DocumentSnapshot>(context);

    List taskList = [];    <-- (3) Using the list here. 

    taskList = userTaskDone['tasks'].toList();

    print(taskList);


声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM