【问题标题】:How to reference variable in method in FutureBuilder (builder:)?如何在 FutureBuilder (builder:) 中的方法中引用变量?
【发布时间】:2020-04-01 14:23:48
【问题描述】:

我想在未来的 Builder builder 中使用 inputData() 中的变量 dbRef:你可以看到星号之间的变量。

void inputData() async {
        FirebaseUser user = await FirebaseAuth.instance.currentUser();
        final uid = user.uid;
      final **dbRef** = FirebaseDatabase.instance.reference().child("Add Job Details").child(uid).child("Favorites");
      }

     @override
      Widget build(BuildContext context) {
        return FutureBuilder (

            future: **dbRef**.once(),
            builder: (context, AsyncSnapshot<DataSnapshot> snapshot) {
              if (snapshot.hasData) {
                List<Map<dynamic, dynamic>> list = [];
                for (String key in snapshot.data.value.keys) {
                  list.add(snapshot.data.value[key]);
                }

【问题讨论】:

  • 您需要使用有状态的小部件。在您的类中使用全局 dbref 变量。你的 inputData() 方法什么时候被调用?
  • 其实我不需要我创建的输入法来获取用户ID。对于用户 ID,我无法在没有方法的情况下获得它。现在的问题实际上是我想要没有任何方法的当前用户 ID,以便我可以在 Widget 中访问它。
  • 我曾经遇到过类似的问题。我不得不重做很多代码。有一些方法可以克服这个问题。一种是在应用程序的开头获取用户/ uid 并将其保存在类中的静态变量中(不共享首选项,因为您需要一个函数来再次检索它)。这是假设您的 uid 永远不会改变。
  • 能否以代码的形式给我一个例子。我希望通过飞镖页面访问用户 ID
  • 当然。给我一些时间,我会写一个飞镖代码并发布答案。

标签: flutter firebase-realtime-database dart


【解决方案1】:

这是解决问题的另一种方法。

这个想法是使用一个变量 _loading 并最初将其设置为 true。 现在,在您的 inputData() 函数之后,您可以在获得 dbref 后将其设置为 false。 存储 dbref,即我在下面的代码中存储 _myFuture 的方式,即在类中全局存储。

如果 _loading 变量为真,则使用您的 _loading 变量返回进度条,否则返回 FutureBuilder 并使用您的 dbref.once()。现在,您已经加载了它,此时它应该是可用的。

class MyWidget extends StatefulWidget {
  @override
  createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {

  // Is the future being loaded? 
  bool _loading;

  // This is the future we will be using in our FutureBuilder.
  // It is currently null and we will assign it in _loadMyFuture function.
  // Until assigned, we will keep the _loading variable as true.
  Future<String> _myFuture;

  // Load the _myFuture with the future we are going to use in FutureBuilder
  Future<void> _loadMyFuture() async {
    // Fake the wait for 2 seconds
    await Future.delayed(const Duration(seconds: 2));

    // Our fake future that will take 2 seconds to return "Hello"
    _myFuture = Future(() async {
      await Future.delayed(const Duration(seconds: 2));
      return "Hello";
    });
  }

  // We initialize stuff here. Remember, initState is called once in the beginning so hot-reload wont make flutter call it again
  @override
  initState() {
    super.initState();
    _loading = true; // Start loading
    _loadMyFuture().then((x) => setState(() => _loading = false)); // Set loading = false when the future is loaded
  }

  @override
  Widget build(BuildContext context) {
    // If loading, show loading bar
    return _loading?_loader():FutureBuilder<String>(
      future: _myFuture,
      builder: (context, snapshot) {
        if(!snapshot.hasData) return _loader(); // still loading but now it's due to the delay in _myFuture
        else return Text(snapshot.data);
      },
    );
  }

  // A simple loading widget
  Widget _loader() {
    return Container(
      child: CircularProgressIndicator(),
      width: 30,
      height: 30
    ); 
  }
}

这是这种方法的输出

这可以完成这项工作,但是您可能需要为每个需要您的 uid 的班级都这样做。

=========================================

这是我在 cmets 中描述的方法。

// Create a User Manager like this
class UserManager {
  static String _uid;

  static String get uid => _uid;

  static Future<void> loadUID() async {
    // Your loading code
    await Future.delayed(const Duration(seconds: 5));
    _uid = '1234'; // Let's assign it directly for the sake of this example
  }
}

在欢迎屏幕中:

class MyWidget extends StatefulWidget {
  @override
  createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  bool _loading = true;

  @override
  void initState() {
    super.initState();
    UserManager.loadUID().then((x) => setState(() => _loading = false));
  }

  @override
  Widget build(BuildContext context) {
    return _loading ? _loader() : Text('Welcome User ${UserManager.uid}!');
  }

  // A simple loading widget
  Widget _loader() {
    return Container(child: CircularProgressIndicator(), width: 30, height: 30);
  }
}

这种方法的好处是一旦你加载了uid,你就可以像这样直接访问它:

String uid = UserManager.uid;

从而消除了期货的使用。

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-03
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多