首页 > 解决方案 > 我如何等待未来的请求?

问题描述

我从 android studio 的控制台收到此消息错误:

════════ (3) Exception caught by widgets library ═══════════════════════════════════════════════════
The method '[]' was called on null.
Receiver: null
Tried calling: [](0)
The relevant error-causing widget was: 
  FutureBuilder<dynamic> file:///home/developer/projects/PaladinsStats/lib/screens/transferencia/formulario.dart:26:15
════════════════════════════════════════════════════════════════════════════════════════════════════

但是当我的请求得到响应时,我的页面就会正常加载。通常我会放一个检查器来查看要渲染的对象是否为空,但我不知道这里发生了什么。我认为他正在尝试访问一个空变量,但构建器等待未来呈现?如果没有,我怎样才能让建造者等待未来?

我的代码:

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import '../../models/champion.dart';

class FormularioTransferencia extends StatefulWidget {
  final Champion champion;

  const FormularioTransferencia({Key key, @required this.champion})
      : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return FormularioTransferenciaState();
  }
}

class FormularioTransferenciaState extends State<FormularioTransferencia> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.champion.feName),
        ),
        body: FutureBuilder(
          future: fetchPost(widget.champion.feName),
          builder: (context, snapshot) {
            final champion = json.decode(snapshot.data.toString());
            return SingleChildScrollView(
              child: Column(
                children: <Widget>[
                  Image.network(
                      'https://web2.hirez.com/paladins/champion-headers/' +
                          champion[0]['slug'] +
                          '.png'),
                ],
              ),
            );
          },
        ));
  }

  fetchPost(championName) async {
    final response = await http.get(
        'https://cms.paladins.com/wp-json/wp/v2/champions?slug=' +
            championName.replaceAll(' ', '-').toLowerCase() +
            '&lang_id=1');

    if (response.statusCode == 200) {
      // If the call to the server was successful, parse the JSON
      return response.body;
    } else {
      // If that call was not successful, throw an error.
      throw Exception('Failed to load post');
    }
  }
}

飞镖型号:

class Champion {
  int id;
  String name;
  String feName;
  String title;
  String role;
  String feRole;
  String image;
  String latest;

  Champion(
      {this.id,
      this.name,
      this.feName,
      this.title,
      this.role,
      this.feRole,
      this.image,
      this.latest});

  Champion.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    name = json['name'];
    feName = json['feName'];
    title = json['title'];
    role = json['role'];
    feRole = json['feRole'];
    image = json['image'];
    latest = json['latest'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id'] = this.id;
    data['name'] = this.name;
    data['feName'] = this.feName;
    data['title'] = this.title;
    data['role'] = this.role;
    data['feRole'] = this.feRole;
    data['image'] = this.image;
    data['latest'] = this.latest;
    return data;
  }
}

标签: flutterdart

解决方案


第一次调用 build() 时,snapshot.data 为 null。当 future 方法返回一个值时,小部件将被重建。

因此,您应该执行以下操作:

return FutureBuilder(
  future:
      getSomeFuture(),
  builder: (context, snapshot) {
    if (snapshot.data == null) { //<-- Add this condition
      return Container();
    } else {
      return MyWidget(snapshot.data);
    }
  }
);

编辑:

如果你想让它看起来不错,使用加载动画作为临时占位符,并确保它与未来返回时构建的小部件具有相同的高度/宽度。


推荐阅读