Как передать значение из одного класса в другой во Flutter

Есть вот такая реализация PaginatedDataTable:

class PaginatedDataTableExample extends StatefulWidget {
  const PaginatedDataTableExample({super.key});

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

class _PaginatedDataTableExampleState extends State<PaginatedDataTableExample> {
  int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: PaginatedDataTable(
          rowsPerPage: _rowsPerPage,
          onRowsPerPageChanged: (newRowsPerPage) {
            setState(() {
              _rowsPerPage = newRowsPerPage!;
            });
          },
          columns: const [
            DataColumn(
              label: Text(
                "id",
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
            ),
            DataColumn(
              label: Text(
                "Begin",
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
            ),
            DataColumn(
              label: Text(
                "End",
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
            ),
          ],
          source: DataTableSourceExample(),
        ),
      ),
    );
  }
}

И DataTableSource для него:

class DataTableSourceExample extends DataTableSource{
  final List<Map<String, dynamic>> data = List.generate(
    999999,
    (index) => {
      "id": index,
      "begin_datetime": DateTime.now(),
      "end_date": DateTime.now(),
    },
  );


  @override
  DataRow? getRow(int index) {
    return DataRow(cells: [
      DataCell(Text(data[index]["id"].toString())),
      DataCell(Text(data[index]["begin_datetime"].toString())),
      DataCell(Text(data[index]["end_date"].toString())),
    ],
    );
  }

  @override
  bool get isRowCountApproximate => false;

  @override
  int get rowCount => data.length;

  @override
  int get selectedRowCount => 0;

}

Но в DataTableSourceExample список заранее создан (просто для теста). В дальнейшем планируется обращаться к стороннему API, в котором записей будет под миллион и больше, не хотелось бы тянуть их все сразу. Поэтому я хочу загружать из API только то количество записей, которые необходимо отобразить на странице.

Поэтому вопрос: как в DataTableSourceExample передать из PaginatedDataTableExample количество строк на странице (я так понимаю, rowsPerPage) и индекс элемента, с которого нужно загружать необходимое количество строк?


Ответы (1 шт):

Автор решения: MiT

Это очень абстрактно (и не красиво), но примерно так:

class DataTableSourceExample extends DataTableSource {
  final int rowsPerPage;
  int _currentStartIndex = 0;
  List<Map<String, dynamic>>? _cachedData;

  DataTableSourceExample({
    required this.rowsPerPage,
  });

  Future<void> fetchData(int startIndex) async {
    // Здесь будет ваш API-запрос
    // Например:
    // final response = await api.getData(startIndex, rowsPerPage);
    // _cachedData = response.data;
    
    // Для примера используем генерацию данных
    _cachedData = List.generate(
      rowsPerPage,
      (index) => {
        "id": startIndex + index,
        "begin_datetime": DateTime.now(),
        "end_date": DateTime.now(),
      },
    );
    _currentStartIndex = startIndex;
    notifyListeners();
  }

  @override
  DataRow? getRow(int index) {
    if (_cachedData == null || 
        index < _currentStartIndex || 
        index >= _currentStartIndex + rowsPerPage) {
      fetchData(index);
      return null;
    }

    final localIndex = index - _currentStartIndex;
    final item = _cachedData![localIndex];
    
    return DataRow(cells: [
      DataCell(Text(item["id"].toString())),
      DataCell(Text(item["begin_datetime"].toString())),
      DataCell(Text(item["end_date"].toString())),
    ]);
  }

  @override
  bool get isRowCountApproximate => false; // TODO: ???

  @override
  int get rowCount => 1000000; // TODO: Общее количество записей с API

  @override
  int get selectedRowCount => 0; // TODO: ???
}
class _PaginatedDataTableExampleState extends State<PaginatedDataTableExample> {
  int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage;
  late DataTableSourceExample _dataTableSource;

  @override
  void initState() {
    super.initState();
    _dataTableSource = DataTableSourceExample(rowsPerPage: _rowsPerPage);
    _dataTableSource.fetchData(0); // Загружаем первую страницу
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: PaginatedDataTable(
          rowsPerPage: _rowsPerPage,
          onRowsPerPageChanged: (newRowsPerPage) {
            setState(() {
              _rowsPerPage = newRowsPerPage!;
              _dataTableSource = DataTableSourceExample(rowsPerPage: _rowsPerPage);
              _dataTableSource.fetchData(0);
            });
          },
          columns: const [
            DataColumn(
              label: Text(
                "id",
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
            ),
            DataColumn(
              label: Text(
                "Begin",
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
            ),
            DataColumn(
              label: Text(
                "End",
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
            ),
          ],
          source: _dataTableSource,
        ),
      ),
    );
  }
}
→ Ссылка