Попытка отобразить текст из пустоты/строки и получить «Закрытие: (динамическое) => пустота из функции?

#android #string #flutter #dart #text

Вопрос:

Итак, я пытаюсь отобразить текст из моего пустого файла в другом файле сценария. Я не получаю никаких ошибок, но я получаю некоторые сообщения вместо отображаемого текста. (Закрытие: (динамическое) => пустота из функции «rannn»:. Задачи)

Кто-нибудь может помочь мне, как исправить эту проблему, чтобы она отображала текст?

Вот мой код

 class TaskData extends ChangeNotifier {
  List<Task> _tasks = [
    Task(name: "Task one"),
    Task(name: "Task two"),
    Task(name: "Task three"),
  ];

  UnmodifiableListView<Task> get tasks {
    return UnmodifiableListView(_tasks);
  }

  void rannn(String) async {
    var randomItem = (_tasks.toList()..shuffle()).first.name;
    print(randomItem);
    //notifyListeners();
  }
 

введите код здесь

 Widget build(BuildContext context) => Container(
        color: Colors.transparent,
        child: Scaffold(
          //backgroundColor: Colors.transparent,
          backgroundColor: Colors.blue,
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                //SizedBox(height: 10),
                Text(
                  "${Provider.of<TaskData>(context).rannn} Tasks",
                ),
                //SizedBox(height: 10),//puts empty box to space things out
                buildTimer(),
                //const SizedBox(height: 10),
                buildButtons(),
              ],
            ),
          ),
        ),
      );
 

Большое вам спасибо!

Добавлен код таймера

 class SecondRoute extends StatefulWidget {
  @override
  CustomMainPageState createState() => CustomMainPageState();
}

class CustomMainPageState extends State<SecondRoute> {
      static const maxSeconds = 5;
      int seconds = maxSeconds;
      Timer? timer;
    
      void resetTimer() => setState(() => seconds = maxSeconds);
    
      void startTimer({bool reset = true}) {
        if (reset) {
          resetTimer();
        }
        timer = Timer.periodic(Duration(seconds: 1), (_) {
          //add here instead seconds say minutes/miliseconds
          if (!mounted) // Putting this line of code with return under, fixed my issue i been having about mounted
            return;
          else if (seconds > 0) {
            setState(() => seconds--);
          } else {
            stopTimer(reset: false);
          }
        });
      }
    
      void stopTimer({bool reset = true}) {
        if (reset == mounted) {
          resetTimer();
        }
        setState(() => timer?.cancel());
      }
    
      Widget build(BuildContext context) => Container(
            color: Colors.transparent,
            child: Scaffold(
              //backgroundColor: Colors.transparent,
              backgroundColor: Colors.blue,
              body: Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    FutureBuilder(
                      future: Provider.of<TaskData>(context).rann(),
                      builder: (context, snapshot) {
                        return Text(
                          "${snapshot.data}",
                          style: TextStyle(
                              color: Colors.white,
                              fontSize: 35,
                              fontWeight: FontWeight.w700),
                        );
                      },
                    ),
                    //SizedBox(height: 10),
                    //SizedBox(height: 10),//puts empty box to space things out
                    buildTimer(),
                    //const SizedBox(height: 10),
                    buildButtons(),
                  ],
                ),
              ),
            ),
          );
    
      @override
      Widget buildButtons() {
        final isRunning = timer == null ? false : timer!.isActive;
        final isCompleted = seconds == maxSeconds || seconds == 0;
        return isRunning || !isCompleted
            ? Row(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  ButtonWidget(
                    text: isRunning ? "Pause" : "Resume",
                    onClicked: () {
                      if (isRunning) {
                        stopTimer(reset: false);
                      } else {
                        startTimer(reset: false);
                      }
                    },
                  ),
                  const SizedBox(width: 12),
                  ButtonWidget(text: "Cancel", onClicked: stopTimer)
                ],
              )
            : ButtonWidget(
                text: "Start Timer!",
                color: Colors.black,
                backgroundColor: Colors.white,
                onClicked: () {
                  startTimer();
                },
              );
      }
    
      Widget buildTimer() => SizedBox(
            width: 200,
            height: 200,
            child: Stack(
              fit: StackFit.expand,
              children: [
                CircularProgressIndicator(
                  value: seconds / maxSeconds,
                  //if you delete 1 - then it goes to other direction
                  valueColor: AlwaysStoppedAnimation(Colors.white),
                  strokeWidth: 12,
                  backgroundColor: Colors.greenAccent,
                ),
                Center(child: buildTime()),
              ],
            ),
          );
    
      Widget buildTime() {
        if (seconds == 0) {
          return Icon(Icons.done, color: Colors.greenAccent, size: 112);
        } else {
          return Text(
            "$seconds",
            style: TextStyle(
              fontWeight: FontWeight.bold,
              color: Colors.white,
              fontSize: 80,
            ),
          );
        }
      }
    }
 

Ответ №1:

Ты делаешь три вещи неправильно.

Во-первых: void rannn(String) это функция, если вы просто попытаетесь распечатать функцию, вы получите именно то, что получаете сейчас.

Во-вторых: void rannn(String) это функция void, поэтому она не вернет a Future<String> для отображения. Вы должны вернуть из него строку, например:

 Future<String> rann() async {
  return (_tasks.toList()..shuffle()).first.name;
}
 

Третье: вы должны вызвать функцию с () , чтобы иметь доступ к ее return значению:

 "${Provider.of<TaskData>(context).rannn()} Tasks",
 

Проблема в том, что это функция , которая возвращает a Future , поэтому она тоже не будет работать.

Решение состоит в том, чтобы использовать FutureBuilder виджет, чтобы вы могли перейти Provider.of<TaskData>(context).rannn() к его параметру будущего и дождаться, пока возвращенное будущее, наконец, отобразит его в вашем Text виджете

Пример:

 Future<String> rannn() async {
  await Future.delayed(const Duration(seconds: 2)); // Just so you can see the Future loading
  return (_tasks.toList()..shuffle()).first.name;
}


Widget build(BuildContext context) => Container(
  color: Colors.transparent,
  child: Scaffold(
    backgroundColor: Colors.blue,
    body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          FutureBuilder(
            future: Provider.of<TaskData>(context).rannn(),
            builder: (context, snapshot) {
              if (!snapshot.hasData) {
                return const Text('Loading...');
              }
              return Text('${snapshot.data}');
            },
          ),
        ],
      ),
    ),
  ),
);
 

Комментарии:

1. Большое вам спасибо за помощь. Я просмотрел документацию по будущему конструктору, но, похоже, не могу понять, где/как использовать этот виджет, не могли бы вы помочь мне с этим?

2. конечно, я покажу вам, я редактирую ответ

3. Хорошо, большое вам спасибо ! Мне удалось выяснить что-то подобное через 2 часа, но это приводит меня в «плохое состояние».

4. @переопределите сборку виджета(контекст BuildContext) { верните новый FutureBuilder( будущее: Поставщик<TaskData>(контекст). rann(), конструктор: (контекст BuildContext, AsyncSnapshot<TaskData><Строка> текст) { верните новый контейнер( дочерний элемент: новый текст( text.requireData, //text.requireData, — работает, но показывает плохое состояние: снимок не содержит ни данных, ни ошибок стиль: новый стиль текста( вес шрифта: вес шрифта.полужирный, размер шрифта: 19.0, ), )); }); }

5. добавлен пример