Мой futurebuilder выдает ошибку в течение нескольких секунд на экране, а затем показывает результат: журналы ошибок

Вот журнал ошибок, который у меня есть в IDE.

Restarted application in 1,172ms.
I/flutter (24036): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (24036): The following NoSuchMethodError was thrown building FutureBuilder<String>(dirty, state:
I/flutter (24036): _FutureBuilderState<String>#bf7da):
I/flutter (24036): The getter 'length' was called on null.
I/flutter (24036): Receiver: null
I/flutter (24036): Tried calling: length
I/flutter (24036):
I/flutter (24036): The relevant error-causing widget was:
[38;5;248mI/flutter (24036):   FutureBuilder<String>[39;49m
I/flutter (24036):
I/flutter (24036): When the exception was thrown, this was the stack:
[38;5;244mI/flutter (24036): #0      Object.noSuchMethod  (dart:core-patch/object_patch.dart:53:5)[39;49m
[38;5;248mI/flutter (24036): #1      _JsonDataState.build.<anonymous closure>[39;49m
[38;5;244mI/flutter (24036): #2      _FutureBuilderState.build[39;49m
[38;5;244mI/flutter (24036): #3      StatefulElement.build[39;49m
[38;5;244mI/flutter (24036): #4      ComponentElement.performRebuild[39;49m
[38;5;244mI/flutter (24036): #5      StatefulElement.performRebuild[39;49m
[38;5;244mI/flutter (24036): #6      Element.rebuild[39;49m
[38;5;244mI/flutter (24036): #7      ComponentElement._firstBuild[39;49m
[38;5;244mI/flutter (24036): #8      StatefulElement._firstBuild[39;49m
[38;5;244mI/flutter (24036): #9      ComponentElement.mount[39;49m
I/flutter (24036): ...     Normal element mounting (22 frames)
[38;5;244mI/flutter (24036): #31     Element.inflateWidget[39;49m
[38;5;244mI/flutter (24036): #32     MultiChildRenderObjectElement.mount[39;49m
I/flutter (24036): ...     Normal element mounting (193 frames)
[38;5;244mI/flutter (24036): #225    Element.inflateWidget[39;49m
[38;5;244mI/flutter (24036): #226    MultiChildRenderObjectElement.mount[39;49m
I/flutter (24036): ...     Normal element mounting (253 frames)
[38;5;244mI/flutter (24036): #479    Element.inflateWidget[39;49m
[38;5;244mI/flutter (24036): #480    Element.updateChild[39;49m
[38;5;244mI/flutter (24036): #481    RenderObjectToWidgetElement._rebuild[39;49m
[38;5;244mI/flutter (24036): #482    RenderObjectToWidgetElement.mount[39;49m
[38;5;244mI/flutter (24036): #483    RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous

закрытие>[39;49m [38;5;244mI/flutter (24036): #484 BuildOwner.buildScope[39;49m [38;5;244mI/flutter] (24036): #485 RenderObjectToWidgetAdapter.attachToRenderTree[39;49m [38];5;244mI/flutter (24036): #486 WidgetsBinding.attachRootWidget[39;49m [38;5;244mI/flutter (24036): #487 WidgetsBinding.scheduleAttachRootWidget.[39;49m I/flutter (24036): (исключено) 11 кадров из класса _RawReceivePortImpl, класса _Timer, dart:async и dart:async-patch) I/flutter (24036): I/flutter (24036): â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â • â •

[38;5;248m════════ Exception caught by widgets library ═══════════════════════════════════[39;49m
[38;5;244mThe following NoSuchMethodError was thrown building FutureBuilder<String>(dirty, state:

_FutureBuilderState#bf7da):[39;49m Получатель 'length' был вызван для нулевого значения. Получатель: null Пробный вызов: длина

[38;5;244mThe relevant error-causing widget was[39;49m
    [38;5;248mFutureBuilder<String>[39;49m
[38;5;244mWhen the exception was thrown, this was the stack[39;49m
[38;5;244m#0      Object.noSuchMethod  (dart:core-patch/object_patch.dart:53:5)[39;49m
[38;5;248m#1      _JsonDataState.build.<anonymous closure>[39;49m
[38;5;244m#2      _FutureBuilderState.build[39;49m
[38;5;244m#3      StatefulElement.build[39;49m
[38;5;244m#4      ComponentElement.performRebuild[39;49m
[38;5;244m...[39;49m
[38;5;248m════════════════════════════════════════════════════════════════════════════════[39;49m

Вот код, который работает. приложение работает, но при запуске появляется ошибка и красный экран в течение нескольких секунд.

`import 'dart:convert';
import 'package:flutter/material.dart';

class JsonData extends StatefulWidget {
  @override
  _JsonDataState createState() => _JsonDataState();
}

class _JsonDataState extends State<JsonData> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Page Data Visualization'),
      ),
      body: Center(
        child: FutureBuilder(
            builder: (context, snapshot) {
              var myData = json.decode(snapshot.data.toString());
              return ListView.builder(
                itemBuilder: (BuildContext context, int index) {
                  return Card(
                    child: ListTile(
                      leading: CircleAvatar(
                          child: Text(myData[index]['trade_code'][0])),
                      title: Text(myData[index]['trade_code']),
                      subtitle: Column(
                        crossAxisAlignment: CrossAxisAlignment.stretch,
                        children: <Widget>[
                          Text(
                            "\nHigh:" + myData[index]['high'],
                            style: TextStyle(fontWeight: FontWeight.bold),
                            textAlign: TextAlign.left,
                          ),
                          Text(
                            "Low:" + myData[index]['low'],
                            style: TextStyle(fontWeight: FontWeight.bold),
                            textAlign: TextAlign.left,
                          ),
                          Text(
                            "Open:" + myData[index]['open'],
                            style: TextStyle(fontWeight: FontWeight.bold),
                            textAlign: TextAlign.left,
                          ),
                          Text(
                            "Close:" + myData[index]['close'],
                            style: TextStyle(fontWeight: FontWeight.bold),
                            textAlign: TextAlign.left,
                          ),
                          Text(
                            "Volume:" + myData[index]['volume'],
                            style: TextStyle(fontWeight: FontWeight.bold),
                            textAlign: TextAlign.left,
                          ),
                          Text(
                            "\nDate:" + myData[index]['date'],
                            style: TextStyle(fontWeight: FontWeight.bold),
                            textAlign: TextAlign.center,
                          ),
                        ],
                      ),
                      isThreeLine: true,
                    ),
                    elevation: 3,
                  );
                },
                itemCount: myData.length,
              );
            },
            future: DefaultAssetBundle.of(context)
                .loadString("assets/stock_market_data.json")),
      ),
    );
  }
}
`

1 ответ

Решение

Ваша функция построителя выполняется несколько раз. Во-первых, без данных. Позже с данными.

Однако вы предполагаете, что у него всегда есть данные, сделав следующее:

              var myData = json.decode(snapshot.data.toString());

Вот, snapshot.dataизначально имеет значение null. Вот почему вы получаете исключение.

Просто следуйте шаблону в документации. https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html

        if (snapshot.hasData) {
          var myData = json.decode(snapshot.data.toString());
        } else if (snapshot.hasError) {
          // show error widget
        } else {
          // show loading widget
        }

несколько конкретных примеров из моего недавнего выступления:

https://youtu.be/p8dY_tsAbx8?t=5382

https://youtu.be/p8dY_tsAbx8?t=5633

Кроме того, это использование тоже нехорошо, вы создаете будущее каждый раз, когда выполняется функция сборки:

            future: DefaultAssetBundle.of(context)
                .loadString("assets/stock_market_data.json")),

Вместо этого вы должны кэшировать это будущее в iniState. Объясняется здесь: https://youtu.be/p8dY_tsAbx8?t=5683

Другие вопросы по тегам