如何在不同的 dart 文件上设置 Future Builder 函数?

How can I set a Future Builder Function on a different dart file?

我有一个未来(异步)日期和时间选择器函数,它在我的有状态小部件的 body 中运行良好,其中包含“Builder”,并且可以通过 onpressed 调用该函数:

onPressed: () {SelectDayAndTimeL();}, 

代码:

Future _selectDayAndTimeL(BuildContext context) async {
    DateTime _selectedDay = await showDatePicker(
        context: context,
        initialDate: DateTime.now(),
        firstDate: DateTime(2021),
        lastDate: DateTime(2030),
        builder: (BuildContext context, Widget child) => child);

    TimeOfDay _selectedTime = await showTimePicker(
      context: context,
      initialTime: TimeOfDay.now(),
    );

    if (_selectedDay != null && _selectedTime != null) {
      //a little check
    }
    setState(() {
      selectedDateAndTime = DateTime(
        _selectedDay.year,
        _selectedDay.month,
        _selectedDay.day,
        _selectedTime.hour,
        _selectedTime.minute,
      );
      // _selectedDate = _selectedDay;
    });
    // print('...');
  }

现在我希望能够从不同的 dart 调用此函数 files/screens 这意味着我必须将此函数保留在我尝试过的不同的 dart 文件中,但是由于它需要在有状态的小部件中发挥作用。我尝试将其放入有状态小部件中,但一直出现错误。

class Picker extends StatefulWidget {
  @override
  _PickerState createState() => _PickerState();
}

class _PickerState extends State<Picker> {
  @override
  Future<Widget> build(BuildContext context) async { //the error in on the build on this line
    DateTime _selectedDay = await showDatePicker(
        context: context,
        initialDate: DateTime.now(),
        firstDate: DateTime(2021),
        lastDate: DateTime(2030),
        builder: (BuildContext context, Widget child) => child);

    TimeOfDay _selectedTime = await showTimePicker(
      context: context,
      initialTime: TimeOfDay.now(),
    );

    if (_selectedDay != null && _selectedTime != null) {
      //a little check
    }
    setState(() {
      selectedDateAndTime = DateTime(
        _selectedDay.year,
        _selectedDay.month,
        _selectedDay.day,
        _selectedTime.hour,
        _selectedTime.minute,
      );
      // _selectedDate = _selectedDay;
    });
  }
}

如何将 Future Function 正确放置在有状态小部件中以及如何在 onpressed 上调用它?

我不知道我给这个问题的标题是否真的是它应该是的,但我不知道该怎么说。

创建一个将日期时间作为参数并设置有状态小部件状态的函数。将其写在有状态小部件中。将此函数作为参数传递给另一个 class。选择日期后,通过传递所选的日期时间来调用此方法。

您应该将 setState 函数本身作为参数传递给该方法。这样,在方法内部您将始终使用正确的状态 setter 函数。这是特别必要的,因为您需要将变量 _selectedDay 等保留在小部件内,而不是在静态方法上。试试这个:

Future selectDayAndTimeL(BuildContext context, Function(DateTime) dateTimeSetter) async { //add a function to receive and use the
    DateTime _selectedDay = await showDatePicker(
        context: context,
        initialDate: DateTime.now(),
        firstDate: DateTime(2021),
        lastDate: DateTime(2030),
        builder: (BuildContext context, Widget child) => child);

    TimeOfDay _selectedTime = await showTimePicker(
      context: context,
      initialTime: TimeOfDay.now(),
    );

    if (_selectedDay != null && _selectedTime != null) {
      //a little check
    }
    // Create the variable with the picked date
    DateTime selectedDateAndTime = DateTime(
        _selectedDay.year,
        _selectedDay.month,
        _selectedDay.day,
        _selectedTime.hour,
        _selectedTime.minute,
      );
     //call the function from the parameter, which will be executed on the calling widget
    dateTimeSetter(selectedDateAndTime);
    ....
}

然后,调用您的函数以显示传递上下文的日期时间选择器,以及一个接收 DateTime 参数的函数,该参数将是用户选择的参数。当用户选择日期时,将执行此函数体,调用 setState 并设置 pickedTime 变量。

class Picker extends StatefulWidget {
  DateTime pickedTime;

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

class _PickerState extends State<Picker> {
  @override
  Future<Widget> build(BuildContext context) async {
     return ...
         _selectDayAndTimeL(context, (DateTime time){
           setState((){
             widget.pickedTime = time;
           });
         });
     ...

您也可以将函数从参数中提取到一个普通的命名函数中,并在参数中使用它的名称,但我暂时保留它以使其更简单。

此外,不要忘记将您的方法设为 public 并在代码范围内根据需要设为静态。

您的方法中的整个 setState 都是问题所在。您的方法应该做 一件事:从用户那里获取日期和时间。责任到此结束。

Future<DateTime> SelectDayAndTimeL(BuildContext context) async {
    DateTime _selectedDay = await showDatePicker(
        context: context,
        initialDate: DateTime.now(),
        firstDate: DateTime(2021),
        lastDate: DateTime(2030),
        builder: (BuildContext context, Widget child) => child);

    TimeOfDay _selectedTime = await showTimePicker(
      context: context,
      initialTime: TimeOfDay.now(),
    );

    if (_selectedDay != null && _selectedTime != null) {
      //a little check
    }
    return DateTime(
        _selectedDay.year,
        _selectedDay.month,
        _selectedDay.day,
        _selectedTime.hour,
        _selectedTime.minute,
      );
  }

现在你的 onPressed 变为:

onPressed: () async { 
     final pickedDatetime = await SelectDayAndTimeL(context); 
     setState(() { selectedDateAndTime = pickedDatetime });
},

您已成功将代码分为选取事物的函数和在选取事物后更新的小部件。

选择日期和时间的函数现在可以在所有其他小部件中重复使用。