String возвращает значение NULL после выхода из дочернего процесса при извлечении из firebase - PullRequest
0 голосов
/ 16 мая 2019

Я извлекаю данные из базы данных Firebase в реальном времени в мое приложение флаттера, используя следующий код.

class homeScreen extends StatelessWidget{
   final DBRef = FirebaseDatabase.instance.reference();
   final String dataToFetch;
   String name;

...
   getData(name, dataToFetch);
...
   void getData(String name, String dataToFetch){
      DBRef.child("dataToFetch").once().then((DataSnapshot dataSnapShot){
         name = dataSnapShot.value;
         print("one $name");
   });
   print("two $name");
  }
}

Я попытался использовать:

return name;

В getData и вDBRef.child.

Проблема, с которой я столкнулся, заключается в том, что DBRef.child находит именно то, что я ищу, и печатает это в консоли «one».Но строка становится нулевой при выходе из дочернего процесса, поэтому в последнем отчете написано «два NULL».

Мой вопрос: как мне сохранить то, что я извлекаю в DBRef.child, и вернуть это значение в мой другой код??

ОБНОВЛЕНИЕ

Вот обновленный код, благодаря @danypata.

import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_core/firebase_core.dart';
import 'dart:async';

class homeScreenFam extends StatefulWidget{
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<homeScreenFam>{
  final DBRef = FirebaseDatabase.instance.reference();
  String name;

  @override
  void initState(){
    print("1: $name");
    super.initState();
    getData(name, "keyThatIWant");
    print("1.5: $name");
  }

  Widget build(BuildContext context){
    print("2: $name");
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Color(0xffe9e9e9),
        body: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text("Welcome $name!",
              textAlign: TextAlign.center,
            ),
          ],
        ),
      ),
    );
  }

  void getData(String name, String dataToFetch) async{
    DBRef.child(dataToFetch).once().then((DataSnapshot dataSnapShot){
      setState(() { // this will trigger the build method
        name = dataSnapShot.value;  // we update the new value.
        print("3: $name");
      });
      print("4: $name");
    });
    print("5: $name");
  }
}

Проблема сохраняется, просто посмотрите на вывод консоли.

Restarted application in 1 309ms.
I/flutter (26334): 1: null
I/flutter (26334): 5: null
I/flutter (26334): 1.5: null
I/flutter (26334): 2: null
I/flutter (26334): 3: <RightName>
I/flutter (26334): 4: <RightName>
I/flutter (26334): 2: null

Как мы видим, 1, очевидно, должно быть нулевым, потому что у нас еще нет имени.Итак, мы хотим на следующих местах, 2,3,4,5.Но только 3 и 4 есть.

Если я напишу "await" перед DBRef.child ... тогда я получу следующий вывод

Restarted application in 1 269ms.
I/flutter (26334): 1: null
I/flutter (26334): 1.5: null
I/flutter (26334): 2: null
I/flutter (26334): 3: <RightName>
I/flutter (26334): 4: <RightName>
I/flutter (26334): 5: <RightName>
I/flutter (26334): 2: null

Теперь нам не хватает только 1,5 и 2. Я предполагаю, что этоимеет какое-то отношение к пустоте.Но я не уверен, какую мелочь мне не хватает?

ОБНОВЛЕНИЕ 2

  void getData(String paramName, String dataToFetch) async{
    DBRef.child(dataToFetch).once().then((DataSnapshot dataSnapShot){
      setState(() { // this will trigger the build method
        paramName = dataSnapShot.value;  // we update the new value.
        print("3: $paramName");
      });
      print("4: $paramName");
    });
    print("5: $paramName");
  }
}

1 Ответ

1 голос
/ 16 мая 2019

Это из-за асинхронного выполнения кода, чтобы исправить это, вам придется ждать выполнения. Как это:

void getData(String name, String dataToFetch) async{ // NOTE THE ASYNC HERE
    //use await to wait for async execution
    String value = await DBRef.child("dataToFetch").once().then((DataSnapshot dataSnapShot){
         name = dataSnapShot.value;
         print("one $name");
         return name;
   });
   print("two $value");
  }

UPDATE Если вы вызываете этот метод из состояния StatefullWidget, вы должны реализовать его следующим образом:

class _MyHomePageState extends State<MyHomePage> {
  String name; // this property will be updated by the getData

  @override
  void initState() {
    super.initState();
    getData(name, "theKeyYouWant"); // call getData in init state
  }

  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Test App'),
      ),
      body: Text(name)
    );
  }


  void getData(String paramName, String dataToFetch) async {
    DBRef.child("dataToFetch").once().then((DataSnapshot dataSnapShot){
      setState(() { // this will trigger the build method
        name = dataSnapShot.value;  // we update the new value.
      });
    });
  }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...