Flutter FutureBuilder 快照为空,但 Future 做 return 数据

Flutter FutureBuilder Snapshot is null but Future Does return data

在使用Flutter 为Kanboard 开发一个新的应用程序客户端时,我遇到了以下问题。我有一个 FutureBuilder,它应该 return 一个带有项目的 select 下拉菜单,但是由于某种原因,快照数据为空,尽管 Future 方法确实解析并且在 return 上有数据。

完整的 page.dart 代码在这里:https://pastebin.com/J48nxsdZ

出现问题的块如下:

Widget _columnSelect() {
return FutureBuilder(
  future: columnProvider.getColumns(task.projectId),
  builder: (BuildContext context, AsyncSnapshot snapshot) {
    List<DropdownMenuItem<String>> columnList = [];
    if (snapshot.hasData) {
      columnList.add(DropdownMenuItem<String>(
          child: Text('Select Column'), value: 0.toString()));
      _columns = snapshot.data;
    } else {
      columnList.add(DropdownMenuItem<String>(
          child: Text('Loading..'), value: 0.toString()));
    }
    _columns.forEach((column) {
      columnList.add(DropdownMenuItem<String>(
          child: Container(
            child: Text(
              column.title,
            ),
          ),
          value: column.id.toString()));
    });
    return Container(
      // margin: EdgeInsets.only(left: 40.0),
      padding: EdgeInsets.symmetric(horizontal: 20.0),
      child: DropdownButtonFormField(
        icon: Padding(
          padding: const EdgeInsets.only(right: 12),
          child: Icon(Icons.view_column, color: Colors.blue),
        ),
        items: columnList,
        value: _columnId,
        decoration: InputDecoration(helperText: 'Optional'),
        onChanged: (newValue) {
          _columnId = newValue;
        },
      ),
    );
  },
);
}

这是用于用户下拉列表的相同形式的小部件的副本 select。原始小部件(在同一页面中)如下:

Widget _ownerSelect() {
return FutureBuilder(
  future: userProvider.getUsers(),
  builder: (BuildContext context, AsyncSnapshot snapshot) {
    List<DropdownMenuItem<String>> usernameList = [];
    if (snapshot.hasData) {
      usernameList.add(DropdownMenuItem<String>(
          child: Text('Select Owner'), value: 0.toString()));
      _users = snapshot.data;
    } else {
      usernameList.add(DropdownMenuItem<String>(
          child: Text('Loading..'), value: 0.toString()));
    }
    _users.forEach((user) {
      usernameList.add(DropdownMenuItem<String>(
          child: Container(
            child: Text(
              user.name,
            ),
          ),
          value: user.id.toString()));
    });
    return Container(
      // margin: EdgeInsets.only(left: 40.0),
      padding: EdgeInsets.symmetric(horizontal: 20.0),
      child: DropdownButtonFormField(
        icon: Padding(
          padding: const EdgeInsets.only(right: 12),
          child: Icon(Icons.person, color: Colors.blue),
        ),
        items: usernameList,
        value: _ownerId,
        decoration: InputDecoration(helperText: 'Optional'),
        onChanged: (newValue) {
          _ownerId = newValue;
        },
      ),
    );
  },
);
}

出于某种原因,“_columnSelect”AsyncSnapshot 始终为 null,即使 Future 方法工作正常也是如此:

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:kanboard/src/models/column_model.dart';
import 'package:kanboard/src/preferences/user_preferences.dart';

class ColumnProvider {
  final _prefs = new UserPreferences();

  Future<List<ColumnModel>> getColumns(projectId) async {
    final Map<String, dynamic> parameters = {
      "jsonrpc": "2.0",
      "method": "getColumns",
      "id": 887036325,
      "params": {"project_id": projectId}
    };

    final credentials = "${_prefs.username}:${_prefs.password}";

    Codec<String, String> stringToBase64 = utf8.fuse(base64);

    String encoded = stringToBase64.encode(credentials);

    final resp = await http.post(
      Uri.parse(_prefs.endpoint),
      headers: <String, String>{"Authorization": "Basic $encoded"},
      body: json.encode(parameters),
    );

    final decodedData = json.decode(utf8.decode(resp.bodyBytes));
    final List<ColumnModel> columns = [];

    final List<dynamic> results = decodedData['result'];

    if (decodedData == null) return [];

    results.forEach((column) {
      final columnTemp = ColumnModel.fromJson(column);
      columns.add(columnTemp);
    });
    print(columns);
    return columns;
  }
}

“打印(列)”的输出returns:

I/flutter ( 9486): [Instance of 'ColumnModel', Instance of 'ColumnModel', Instance of 'ColumnModel', Instance of 'ColumnModel']

我不知道我在这里错过了什么。该表单有 2 个用户下拉列表 select(使用原始的 FutureBuilder Widget),效果很好。 Future Builder 的列小部件是 snapshot.data.

中存在“空”问题的小部件

提前感谢您的宝贵时间和对此的支持!

我刚找到问题所在:

在表单页面(新任务页面)中,columnProvider.getColumns(task.projectId)) 没有执行,因为“task.projectId”参数是一个字符串,但是 API 需要一个整数。

我很困惑,因为上一页(包含所有任务的项目页面)正在调用该方法,而 getColumn 的参数确实是一个整数:int.parse(projectId)。

如果此特定调用“getColumns”的 ID 参数不是 INT(出于某种原因),看板 API 不会 return 错误代码。

当然,Flutter(或 Dart)正在等待 http.post 永远不会到达的响应。当比较两个页面的两个调用时,我注意到了差异。

因此,总而言之,我在 getColumn 定义中指定了 int 数据类型参数以避免混淆:

Future<List<ColumnModel>> getColumns(int projectId) async {

此致!