是否可以在没有状态管理器的情况下在两个无状态小部件之间实现状态管理?

问题描述

我认为这是正确的问题。我遇到了为了我的演示项目想要保持我的代码超级简洁和简单的问题。我正在使用两个无状态小部件,我希望它们进行通信,也就是说,我希望一个小部件在用户输入时重新加载另一个

附则说明:我开始熟悉主要将 GetX 用于状态管理,因此我想尝试始终使用无状态小部件。请在您的回答中记住这一点。我知道我可以使用 setState() 有状态小部件解决这个问题。我也知道我可以使用扩展 GetXController() 甚至提供程序的控制器类来解决这个问题。然而,我只是好奇,如果没有这些明显的解决方案,我正在尝试做的事情是否可行......

所以.. 问题是:

是否可以让这个小部件的 rangeStart 和 rangeEnd(当被用户日期选择更改时)在下面的下一个小部件中重建文本小部件?

import 'package:Flutter/material.dart';
import 'package:date_range_picker/date_range_picker.dart' as DaterangePicker;

// ignore: must_be_immutable
class Daterange extends StatelessWidget {
  DateTime rangeStart = DateTime.Now().subtract(Duration(days: 7));
  DateTime rangeEnd = DateTime.Now();

  @override
  Widget build(BuildContext context) {
    return IconButton(
        color: Colors.white,icon: Icon(Icons.calendar_today),onpressed: () async {
          final List<DateTime> picked = await DaterangePicker.showDatePicker(
              context: context,initialFirstDate: DateTime.Now().subtract(Duration(days: 7)),initialLastDate: DateTime.Now(),firstDate: DateTime(2015),lastDate: DateTime(DateTime.Now().year + 2));
          if (picked != null && picked.length == 2) {
            rangeStart = picked.first;
            rangeEnd = picked.last;
          }
        });
  }
}
import 'package:Flutter/material.dart';
import 'package:get/get.dart';
import 'package:linechart/add_data_button.dart';
import 'package:linechart/date_range.dart';
import 'package:syncfusion_Flutter_charts/charts.dart';
import 'package:intl/intl.dart';

class LineChartScreen extends StatelessWidget {
  final Daterange daterange = Get.put(Daterange());

  @override
  Widget build(BuildContext context) {
    String startDate = DateFormat.yMMMMd('en_US').format(daterange.rangeStart);
    String endDate = DateFormat.yMMMMd('en_US').format(daterange.rangeEnd);

    return Scaffold(
      appBar: AppBar(
        title: Text('GRAPH --- Range: $startDate - $endDate'),backgroundColor: Colors.lightBlue,actions: [
          AddDataButton(),Daterange(),],),body: Column(...),);
  }
}

解决方法

old post 说明:

StatelessWidget 永远不会自行重建(但可以从外部 事件)。 StatefulWidget 可以。这是黄金法则。

因此您需要某种机制来导致 StatelessWidget 重建,正如您所说,有很多这样的机制。

我喜欢使用 flutter_hooks 作为管理这种私有状态的简单机制。这是使用它的示例的代码。在代码中:

  • 父小部件调用 useState 来定义/访问其状态
  • 子部件调用回调来更新状态,从而导致父部件重建

代码:

import 'package:flutter/material.dart';
import 'package:date_range_picker/date_range_picker.dart' as DateRangePicker;
import 'package:intl/intl.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

// ignore: must_be_immutable
class DateRangeWidget extends StatelessWidget {
  Function _setDateRange;

  DateRangeWidget(this._setDateRange);

  DateTime rangeStart = DateTime.now().subtract(Duration(days: 7));
  DateTime rangeEnd = DateTime.now();

  @override
  Widget build(BuildContext context) {
    return IconButton(
        color: Colors.white,icon: Icon(Icons.calendar_today),onPressed: () async {
          final List<DateTime> picked = await DateRangePicker.showDatePicker(
              context: context,initialFirstDate: DateTime.now().subtract(Duration(days: 7)),initialLastDate: DateTime.now(),firstDate: DateTime(2015),lastDate: DateTime(DateTime.now().year + 2));
          if (picked != null && picked.length == 2) {
            rangeStart = picked.first;
            rangeEnd = picked.last;
            _setDateRange(rangeStart,rangeEnd);
          }
        });
  }
}

class DateRange {
  DateTime rangeStart,rangeEnd;
  DateRange(this.rangeStart,this.rangeEnd);
}

class LineChartScreen extends HookWidget {
//  final DateRange dateRange = Get.put(DateRange());
  @override
  Widget build(BuildContext context) {
    final dateRange = useState(
        DateRange(DateTime.now().subtract(Duration(days: 7)),DateTime.now()));

    void _setDateRange(rangeStart,rangeEnd) {
      dateRange.value = DateRange(rangeStart,rangeEnd);
    }

    String startDate =
        DateFormat.yMMMMd('en_US').format(dateRange.value.rangeStart);
    String endDate =
        DateFormat.yMMMMd('en_US').format(dateRange.value.rangeEnd);

    return Scaffold(
      appBar: AppBar(
        title: Text('GRAPH --- Range: $startDate - $endDate'),backgroundColor: Colors.lightBlue,actions: [
          // AddDataButton(),DateRangeWidget(_setDateRange),],),body: Column(
        children: [
          Text(startDate),Text(endDate),);
  }
}