【问题标题】:How to pass data between classes? Flutter如何在类之间传递数据?扑
【发布时间】:2021-10-24 13:05:49
【问题描述】:

我有一个类,我从用户那里获取电子邮件数据。它基本上是一个文本字段,所以我不会发布文本字段代码。获得电子邮件和密码数据后,我会检查这些数据是否在我的 Firestore 数据库中。如果是,我想将此电子邮件数据传递给我的其他班级,以便我获得有关客户的其他信息。

这是当我单击按钮时尝试检查用户是否存在的代码。这是我的 LoginScreen() 类的 Material Button 的 onPressed 操作。如果用户已经存在于我的 FirebaseAuth 中,我只收到来自用户的电子邮件,并希望将此电子邮件数据传递给我的 CustomerInfo 类。此外,CustomerScreen 类用于在屏幕上显示所有客户信息。成功获取数据表单数据库后,我会添加一些代码来推送客户信息。

try {
                    final user = await _auth.signInWithEmailAndPassword(
                        email: email!, password: password!);
                    if (user != null) {
                      CustomerInfo(email: email);
                      Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (context) => CustomerScreen()));
                    }
                  } catch (e) {
                    print(e);
                  }

我还有另一个类,我正在尝试获取客户数据。

 class CustomerInfo {
  String? email;
  String? name;
  String? surname;
  String? avatarLink;
  int? balance;

  CollectionReference customers =
      FirebaseFirestore.instance.collection('customers');

  CustomerInfo({this.email});

  Future getCustomerData() async {
    print("Email: $email");
    await customers.where('email', isEqualTo: email).get().then((value) {
      value.docs.forEach((result) {
        name = result['name'];
        surname = result['surname'];
        balance = result['balance'];
        avatarLink = result['image'];
      });
    });
  }
}

还有 CustomerInfo 类:

import 'package:banking_app_firebase/constants.dart';
import 'package:banking_app_firebase/networking.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

import 'login_screen.dart';

class CustomerScreen extends StatefulWidget {
  const CustomerScreen({Key? key}) : super(key: key);

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

class _CustomerScreenState extends State<CustomerScreen> {
  String? name;
  String? surname;
  int? balance;
  String? image;

  void getData() async {
    CustomerInfo customerInfo = CustomerInfo();
    await customerInfo.getCustomerData();

    name = customerInfo.name;
    print("Name: $name");
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    getData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        backgroundColor: Colors.white,
        iconTheme: IconThemeData(
          color: Colors.black,
        ),
        title: Text(
          "Account Summary",
          style: TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
            color: Colors.black,
          ),
        ),
        actions: [
          Container(
            padding: EdgeInsets.only(right: 10),
            child: Row(
              children: [
                Icon(
                  CupertinoIcons.bell,
                  color: Colors.black,
                ),
                SizedBox(
                  width: 10,
                ),
                CircleAvatar(
                  backgroundImage: NetworkImage(
                      "https://cdn.pixabay.com/photo/2016/03/23/04/01/woman-1274056_960_720.jpg"),
                ),
              ],
            ),
          ),
        ],
        elevation: 0,
      ),
      body: Container(
        child: Column(
          children: [
            Align(
              alignment: Alignment.topLeft,
              child: Text(
                "Deneme",
                style: kInfoTextDecoration,
              ),
            ),
            Align(
              alignment: Alignment.topLeft,
              child: Text(
                "Deneme",
                style: kInfoTextDecoration,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

如何将电子邮件数据传递给我的 CustomerInfo 类,以便我可以使用 getCustomerData()?使用 CustomerInfo(email:email) 不起作用。

【问题讨论】:

  • 您可以使用 FirebaseAuth 的实例来获取 currentUser。然后您可以使用currentUser.getEmail(); 从 currentUser 获取电子邮件
  • @KshitijDhakal 嘿。我可以在我的基类中收到电子邮件。我想做的只是将此电子邮件数据传递给另一个类。
  • FirebaseAuth.getInstance() 返回单例。所以你应该可以在任何类中使用。
  • @KshitijDhakal 这不是给我一个不必要的 API 调用吗?我只想简单地将已使用的电子邮件数据发送到另一个班级。但我会试试这个。
  • 你为什么要创建一个CustomerInfo(email: email)' in the first code sample (inside the try` 块?您没有将实例保存到变量中,因此您只是创建了一个 CustomerInfo() 而从不使用它。

标签: firebase flutter dart google-cloud-firestore


【解决方案1】:

这取决于您的喜好。例如,通常我会创建一个global.dart 并在其中存储临时变量。例如在你的 global.dart 中:

CustomerInfo selectedUser;

然后你可以在任何你想要的地方设置它。例如:

import './global.dart' as global;

try {
                    final user = await _auth.signInWithEmailAndPassword(
                        email: email!, password: password!);
                    if (user != null) {
                      CustomerInfo(email: email);
                      global.selectedUser = CustomeInfo(SET PARAMETERS);
                      Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (context) => CustomerScreen()));
                    }
                  } catch (e) {
                    print(e);
                  }

你可以在任何你想要的地方调用global.selectedUser来使用它。 其他方法是使用Provider,但当您想要更改许多文件中的变量时它很有用。 此外,您可以使用firebase 方法获取活跃用户和他/她的信息,例如getEmail(),但由于不必要的 API 调用,我不建议这样做。

【讨论】:

  • 我不知道我是否理解正确,但我想将电子邮件数据发送到 CustomerInfo 类。反之则不然。在这段代码中,您试图从 CustomerInfo 类中获取电子邮件,对吗?
  • 实际上,根据我的解决方案,您可以随时随地访问用户信息(客户信息)。例如,如果你想在CustomerInfo class 中访问它,首先import './global.dart' as global; 然后通过global.selectedUser 使用它。
【解决方案2】:

从 _auth 获取电子邮件信息。

  try {
final user = await _auth!.signInWithEmailAndPassword(
    email: email!, password: password!);
if (user.user !=null) {                       // added user.user
  CustomerInfo(email: user.user!.email);     //added user.user!.email
  Navigator.push(
      context,
      MaterialPageRoute(
          builder: (context) => CustomerScreen()));
}
} catch (e) {
print(e);
}

【讨论】:

  • 这又给了我一个错误。我认为尝试像这样发送是行不通的。 @ismail
  • 你在哪一部分得到了错误?是根本没有将数据传递给 CustomerInfo() 类,还是出现差异错误?
  • 如果您检查 CustomerInfo 类,我将在一切开始之前在 getCustomerData() 函数中打印电子邮件数据。使用此解决方案,打印返回 null 值。
【解决方案3】:

这不起作用,因为电子邮件字段不是静态的,因此您不能使用CustomerInfo.getCustomerData()。您需要创建一个自定义用户的实例,然后使用getCustomerData() 方法。

例如:var data = await CustomerInfo(email: email).getCustomerData(); 或者,如果您要多次使用 CustomerInfo()`,您可以执行以下操作:

final CustomerInfo info = CustomerInfo(email: email);

var data = info.getCustomerData();

或类似的东西。

如果您尝试在 CustomScreen() 中显示信息,我认为在此处创建 CustomerInfo() 并获取所需的任何数据可能会更容易。

我所能做的就是猜测,因为您没有提供CustomScreen() 的样本或它的用途。如果您尝试使用CustomScreen() 中的客户数据,那么最好使用FutureBuilder() 向您的用户显示数据正在加载,然后在未来完成后显示它,而不是在推送之前进行异步回调路线让用户认为他们没有点击按钮。

【讨论】:

  • 更好的选择是从FirebaseAuth.getInstance() 获取用户,然后从当前登录的用户获取电子邮件。
【解决方案4】:

对不起,我想我误解了你的问题。

这是你想要做的吗?您正在正确传递电子邮件。您只需拨打getCustomerData()

try {
  final user = await _auth.signInWithEmailAndPassword(
      email: email!, password: password!);
  if (user != null) {
    var customerInfo = CustomerInfo(email: email);
    await customerInfo.getCustomerData();
    Navigator.push(
        context,
        MaterialPageRoute(
            builder: (context) => CustomerScreen(customerInfo: customerInfo)));
  }
} catch (e) {
  print(e);
}

然后在 CustomerScreen 中看起来像这样

class CustomerScreen extends StatefulWidget {
  final CustomerInfo customerInfo;
  const CustomerScreen({Key? key, this.customerInfo}) : super(key: key);

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

class _CustomerScreenState extends State<CustomerScreen> {
  String? name;
  String? surname;
  int? balance;
  String? image;

  void getData()  {
   name = widget.customerInfo.name;
   surname = widget.customerInfo.surname;
   balance = widget.customerInfo.balance;
   image = widget.customerInfo.image;
  }

但我建议你看看 FutureBuilder。

【讨论】:

  • 让我告诉你我在做什么。我有3节课。 LoginScreen、CustomerScreen 和 CustomerInfo。在登录屏幕中,我从用户那里获取电子邮件和密码数据,以检查它是否与我的 Firebase 匹配。如果是,我正在尝试将电子邮件数据传递给 CustomerInfo 类,以获取此用户的所有信息。之后,我会将姓名、姓氏、余额等信息传递给 CustomerScreen 并在我的设计中使用它。我添加了 CustomerScreen 类,以便您检查代码的工作方式。
  • 那您为什么不在 CustomerScreen 中将电子邮件作为参数传递呢?然后在getData()中,可以使用widget.email来获取邮件。
  • 当你创建一个新对象时,它不会保持旧对象的状态,除非它们是单例的。因此,即使您调用了CustomerInfo(email: email),当您调用CustomerInfo customerInfo = CustomerInfo(); 时,它也会创建新实例。它不返回旧实例。
  • 我不想在这些屏幕中的任何一个中执行网络功能。我想在另一个班级做网络工作。但是,我可能会直接在 CustomerScreen 中传递数据
  • 我只是迷失在所有的答案中啊哈哈
猜你喜欢
  • 1970-01-01
  • 2021-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-07
  • 2022-01-20
  • 2022-01-20
  • 2020-04-05
相关资源
最近更新 更多