Ошибка Flutter PaginatedDataTable Future с цепным запросом - PullRequest
0 голосов
/ 05 августа 2020

У меня проблема с моей таблицей PaginatedDataTable во Flutter Web (1.20.0-8.0.pre2): мне нужно связать два будущих запроса, один в зависимости от первого. Например: Первый запрос возвращает массив задач json:

[ ["field1", "field2", 154631565, "field4"],["field5", "field6", 7862626, "field8"] ]"

Число в 3-й позиции - это идентификатор пользователя. Второй запрос получает пользователя с этим:

[ 154631565, "John", "Doe"]

Мой код основан на этом: https://github.com/AseemWangoo/experiments_with_web/tree/master/lib/data_table и https://flatteredwithflutter.com/using-paginateddatatable-in-flutter-web/

Если я запрашиваю только первую конечную точку, все работает, но у меня есть идентификаторы в таблице, а не имя и имя.

TaskDataTableAPi:

class TaskDataTableApi {
  TaskDataTableApi._();

  static Future<List<TaskModel>> fetchData() async {
    final _completer = Completer<List<TaskModel>>();

    try {
      final response = await http.get(_query);

      if (response.statusCode == 200) {
        // print(response.body);
        final _data = taskModelFromJson(response.body.replaceAll(r'\t', ' '));
        _completer.complete(_data);
      } else {
        print('Error, Could not load Data');
        throw Exception('Failed to load Data');
      }
    } catch (exc) {
      _completer.completeError(<TaskModel>[]);
    }

    return _completer.future;
  }
}

UserDataTableApi:

class UserDataTableApi {
  UserDataTableApi._();

  static Future<List<UserModel>> fetchData(maxRows) async {
    final _completer = Completer<List<UserModel>>();
    String _query = url;
    _query += 'selectQuery?loginName=' + loginName;
    _query += '&password=' + password;
    _query += '&custId=' + custId;
    _query += '&maxRows= ' + maxRows;
    _query += '&output=json&';
    _query += 'query=SELECT id, firstName,lastName, photo FROM USER';

    try {
      final response = await http.get(_query);

      if (response.statusCode == 200) {
        print(response.body);
        final _data = userModelFromJson(response.body.replaceAll(r'\t', ' '));
        _completer.complete(_data);
      } else {
        print('Error, Could not load Data');
        throw Exception('Failed to load Data');
      }
    } catch (exc) {
      _completer.completeError(<UserModel>[]);
    }

    return _completer.future;
  }

  static Future<List<UserModel>> getOneById(int id) async {
    final _completer = Completer<List<UserModel>>();
    try {
      final response = await http.get(_query);

      if (response.statusCode == 200) {
        //print(response.body);
        final _data = userModelFromJson(response.body.replaceAll(r'\t', ' '));
        _completer.complete(_data);
      } else {
        print('Error, Could not load Data');
        throw Exception('Failed to load Data');
      }
    } catch (exc) {
      _completer.completeError(<UserModel>[]);
    }

    return _completer.future;
  }
}

TaskDataTableNotifier

class TaskDataNotifier with ChangeNotifier {
  TaskDataNotifier() {
    fetchData();
  }

  List<TaskModel> get taskModel => _taskModel;

  int get sortColumnIndex => _sortColumnIndex;

  set sortColumnIndex(int sortColumnIndex) {
    _sortColumnIndex = sortColumnIndex;
    notifyListeners();
  }

  bool get sortAscending => _sortAscending;

  set sortAscending(bool sortAscendindg) {
    _sortAscending = sortAscending;
    notifyListeners();
  }

  int get rowsPerPage => _rowsPerPage;

  set rowsPerPage(int rowsPerPage) {
    _rowsPerPage = rowsPerPage;
    notifyListeners();
  }

  var _taskModel = <TaskModel>[];

  int _sortColumnIndex;
  bool _sortAscending = true;
  int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage;

  Future<void> fetchData() async {
    _taskModel = await TaskDataTableApi.fetchData();
    for (TaskModel _row in _taskModel) {
      if (_row.dev != null) {
        print(_row.dev);
        // List<UserModel> _user = await UserDataTableApi.getOneById(_row.dev);
        // print(_user[0].firstName);
      }
    }

    notifyListeners();
  }
}

и страница с DataTable:

class MyTasksList extends StatelessWidget {
  const MyTasksList({Key key}) : super(key: key);

  static const String routeName = '/tasks';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: MyAppBar(),
      drawer: MyDrawer(),
      body: ChangeNotifierProvider<TaskDataNotifier>(
        create: (_) => TaskDataNotifier(),
        child: SingleChildScrollView(
          scrollDirection: Axis.vertical,
          child: Center(
            child: Container(
              width: 1500.0,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Padding(
                    padding: EdgeInsets.only(
                      top: 10.0,
                    ),
                    child: _MyTasksList(),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class _MyTasksList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final _provider = context.watch<TaskDataNotifier>();
    final _model = _provider.taskModel;

    if (_model.isEmpty) {
      return const SizedBox.shrink();
    }

    final _dtSource = TaskDataTableSource(
      //onRowSelect: (index) => _showDetails(context, _model[index]),
      onRowSelect: (index) => print("Pressed"),
      taskData: _model,
    );

    return PaginatedDataTable(
      actions: <IconButton>[
        IconButton(
          splashColor: Colors.transparent,
          icon: const Icon(Icons.refresh),
          onPressed: () {
            _provider.fetchData();
            _showSBar(context, "Refresh successful");
          },
        ),
      ],
      header: Text('Task List'),
      columns: myColumns(_dtSource, _provider),
      source: _dtSource,
      onRowsPerPageChanged: (rowsPerPage) {
        _provider.rowsPerPage = rowsPerPage;
      },
      sortAscending: _provider.sortAscending,
      sortColumnIndex: _provider.sortColumnIndex,
      rowsPerPage: _provider.rowsPerPage,
    );
  }

  List<DataColumn> myColumns(
    TaskDataTableSource _src,
    TaskDataNotifier _provider,
  ) =>
      <DataColumn>[
        DataColumn(
          label: Text('Type'),
          onSort: (colIndex, asc) {
            _sort<num>((task) => task.taskType, colIndex, asc, _src, _provider);
          },
        ),
        DataColumn(
          label: Text('Name'),
          onSort: (colIndex, asc) {
            _sort<String>((task) => task.name, colIndex, asc, _src, _provider);
          },
        ),
        DataColumn(
          label: Text('?'),
        ),
        DataColumn(
          label: Text('Origin'),
          onSort: (colIndex, asc) {
            _sort<num>(
                (task) => task.customerId, colIndex, asc, _src, _provider);
          },
        ),
        DataColumn(
          label: Text('Customer'),
          onSort: (colIndex, asc) {
            _sort<num>(
                (task) => task.customerId, colIndex, asc, _src, _provider);
          },
        ),
        DataColumn(
          label: Text('Complexity'),
          onSort: (colIndex, asc) {
            _sort<num>(
                (task) => task.complexity, colIndex, asc, _src, _provider);
          },
        ),
        DataColumn(
          label: Text('Value'),
          onSort: (colIndex, asc) {
            _sort<num>((task) => task.value, colIndex, asc, _src, _provider);
          },
        ),
        DataColumn(
          label: Text('Dev'),
          onSort: (colIndex, asc) {
            _sort<num>((task) => task.dev, colIndex, asc, _src, _provider);
          },
        ),
        DataColumn(
          label: Text('Corr'),
          // onSort: (colIndex, asc) {
          //   _sort<num>((task) => task.cor, colIndex, asc, _src, _provider);
          // },
        ),
        DataColumn(
          label: Text('Status'),
        ),
        DataColumn(
          label: Text('Created on'),
          onSort: (colIndex, asc) {
            _sort<DateTime>(
                (task) => task.createdOn, colIndex, asc, _src, _provider);
          },
        ),
        DataColumn(
          label: Text('Canceled on'),
        ),
        DataColumn(
          label: Text('Super Score'),
        ),
      ];

  void _sort<T>(
    Comparable<T> Function(TaskModel task) getField,
    int colIndex,
    bool asc,
    TaskDataTableSource _src,
    TaskDataNotifier _provider,
  ) {
    _src.sort<T>(getField, asc);
    _provider.sortAscending = asc;
    _provider.sortColumnIndex = colIndex;
  }

  void _showSBar(BuildContext c, String textToShow) {
    Scaffold.of(c).showSnackBar(
      SnackBar(
        content: Text(textToShow),
        duration: const Duration(milliseconds: 2000),
      ),
    );
  }
}

Я пытался вызвать await then () в уведомлении, я вижу, что второй запрос запущен, но затем приложение не удается.

Спасибо за помощь.

1 Ответ

0 голосов
/ 07 августа 2020

Я наконец нашел способ сделать это. Я меняю основной виджет в виджете с отслеживанием состояния и добавляю FutureBuilder. Я удалил класс Provider и использовал setState () для выполнения действий с DataTable. Благодаря этому я могу выполнять несколько операций ожидания и получать полные данные.

...