【问题标题】:'The method 'call' was called on null.' in Flutter'方法'call'在null上被调用。'在颤振中
【发布时间】:2020-08-02 23:43:22
【问题描述】:

我正在尝试从子小部件 PieChartWidget 中提取一个值 touchedIndex,我必须使用 fl_chart 在其父小部件 Co2Tracker 中制作一个中间有一个洞的饼图,以允许我在饼图的中间创建一些文本,当按下饼图的一部分时,这些文本会发生变化。这会返回一个错误,但除饼图段之外的所有内容都可以在视觉上运行。为了使调试更容易,我将setState(){isTouched = isTouchedNew} 替换为print(isTouchedNew),但这仍然返回下面的错误,但是,饼图现在展开了。

PieChart example

使用回调函数时

int isTouched = -1;
setIsTouched(int isTouchedNew) {
  print(isTouchedNew);
}

集成在有状态的小部件中,我得到了输出

════════ Exception caught by gesture ═══════════════════════════════════════════════════════════════
The method 'call' was called on null.
Receiver: null
Tried calling: call(-1)

父主页

class Co2Tracker extends StatefulWidget {
  @override
  _Co2TrackerState createState() => _Co2TrackerState();
}

class _Co2TrackerState extends State<Co2Tracker> {

  List<String> pieNames = ['Travel', 'Gas', 'Electricity', 'Food shop', 'Water',];

  int isTouched = -1;
  double radiusNormal = 60;
  double centerRadius = 50;
  double radiusExpansion = 1.2;

  setIsTouched(int isTouchedNew) {
    print(isTouchedNew);
  }

  @override
  Widget build(BuildContext context) {

    //double co2 = ModalRoute.of(context).settings.arguments;

    return Scaffold(
      appBar: appBarTemplate('CO\u2082 Tracker'),
      body: Column(
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 15),
            child: textStyleTemplateLarge(text: 'Your CO\u2082 emissions today', textColor: Colors.green[400]),
          ),
          AspectRatio(
            aspectRatio: 200/((radiusExpansion*radiusNormal) + centerRadius),
            child: Row(
              children: <Widget>[
                Expanded(
                  child: Stack(
                    children: <Widget>[
                      Center(
                        child: FlatButton(child: textStyleTemplateLarge(text: '70kg', textColor: Colors.black),),
                      ),
                      Center(
                          child: PieChartWidget(radiusNormal: radiusNormal, centerRadius: centerRadius, radiusExpanded: (radiusExpansion*radiusNormal), pieNames: pieNames,),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

子饼图小部件

import 'package:flutter/material.dart';
import 'package:fl_chart/fl_chart.dart';

class PieChartWidget extends StatefulWidget {
  final double radiusNormal;
  final double radiusExpanded;
  final double centerRadius;
  final double fontSizeNormal;
  final double fontSizeExpanded;
  final List<String> pieNames;
  final Function(int) setIsTouched;

  PieChartWidget({this.radiusNormal, this.radiusExpanded, this.centerRadius, this.fontSizeNormal, this.fontSizeExpanded, this.pieNames, this.setIsTouched});



  @override
  _PieChartWidgetState createState() => _PieChartWidgetState(radiusNormal: radiusNormal, radiusExpanded: radiusExpanded, centerRadius: centerRadius,
    fontSizeNormal: fontSizeNormal, fontSizeExpanded: fontSizeExpanded, pieNames: pieNames, setIsTouched: setIsTouched,);
}

class _PieChartWidgetState extends State<PieChartWidget> {
  int touchedIndex = -1;
  double radiusNormal;
  double radiusExpanded;
  double centerRadius;
  double fontSizeNormal;
  double fontSizeExpanded;
  List<String> pieNames;
  Function(int) setIsTouched;

  _PieChartWidgetState({this.radiusNormal = 50, this.radiusExpanded = 60, this.centerRadius = 40, this.fontSizeNormal = 16, this.fontSizeExpanded = 25,
    this.pieNames, this.setIsTouched,});

  @override
  Widget build(BuildContext context) {
    return PieChart(
      PieChartData(
        sections: pieSections(pieNames),
        borderData: FlBorderData(show: false),
        sectionsSpace: 0,
        centerSpaceRadius: centerRadius,
        pieTouchData: PieTouchData(touchCallback: (pieTouchResponse) {
          setState(() {
            if (pieTouchResponse.touchInput is FlLongPressEnd ||
                pieTouchResponse.touchInput is FlPanEnd) {
              touchedIndex = -1;
            } else {
              touchedIndex = pieTouchResponse.touchedSectionIndex;
            }
          });
          widget.setIsTouched(touchedIndex);
        }),
      ),
    );
  }

-----------------I-think-everything-below-this-is-irrelevant-but-I-could-be-wrong-------------------------------------------

  List<PieChartSectionData> pieSections(List<String> pieNames,) {
    return List.generate(5, (i) {
      final isTouched = i == touchedIndex;
      final double fontSize = isTouched ? 25 : 16;
      final double radius = isTouched ? radiusExpanded : radiusNormal;
      final int colorNumber = (1+i) * 100;
      final List<double> valueList = [20, 10, 10, 20, 30];
      final double total = valueList.fold(0, (a, b) => a+b);
      switch (i) {
        case 0:
          return sectionData(valueList[i], Colors.pink[300], title(isTouched, valueList[i], total, pieNames[i]), radius, fontSize);
        case 1:
          return sectionData(valueList[i], Colors.blue[600], title(isTouched, valueList[i], total, pieNames[i]), radius, fontSize);
        case 2:
          return sectionData(valueList[i], Colors.amber[300], title(isTouched, valueList[i], total, pieNames[i]), radius, fontSize);
        case 3:
          return sectionData(valueList[i], Colors.purple[300], title(isTouched, valueList[i], total, pieNames[i]), radius, fontSize);
        case 4:
          return sectionData(valueList[i], Colors.blue[300], title(isTouched, valueList[i], total, pieNames[i]), radius, fontSize);
        default:
          return null;
      }
    });
  }
  PieChartSectionData sectionData(double value, Color color, String title, double radius, double fontSize,){
    return PieChartSectionData(
      value: value, color: color, title: title, radius: radius,
      titleStyle: TextStyle(color: Colors.black, fontSize: fontSize, fontWeight: FontWeight.bold),
    );
  }
  String title(bool isTouched, double value, double total, String title,) {
    return isTouched ? '${double.parse((value/total*100).toStringAsFixed(2))}%' : '$title';
  }
}

到目前为止,我的想法可能与变量的初始化有关,或者可能与子页面第 43 行中的 touchCallback 函数有关,但到目前为止还没有运气。 提前感谢您的宝贵时间。

【问题讨论】:

    标签: android flutter dart mobile


    【解决方案1】:

    问题是当你打印一个整数时。

    setIsTouched(int isTouchedNew) { print(isTouchedNew); }

    你应该像这样打印它

    print("${isTouchedNew}")
    

    【讨论】:

    • 抱歉,这不起作用setIsTouched( int isTouchedNew ) { print("${isTouchedNew}"); } 返回相同的错误,"${isTouchedNew}" 突出显示 在不需要时避免在插值中使用大括号。跨度>
    • 您是否尝试过运行您的代码?因为即使出现此错误“在不需要时避免在插值中使用大括号”,您的应用程序也可以运行。
    • 是的,我确实尝试过,但似乎没有什么不同。如果你想运行代码,我认为你所要做的就是用AppBar() 小部件替换appBarTemplate(),用Text() 小部件替换textStyleTemplateLarge() 模板,并在开始时添加一个MaterialApp() 小部件。
    • 好的,我认为你传递给函数的值是 null
    • setIsTouched 是一个函数而不是小部件
    【解决方案2】:

    嗯..不确定您是否尝试过,

    int isTouched = -1;
    
    
    setIsTouched(int isTouchedNew) {
    setState(() {
    
    isTouched=isTouchedNew;
      print(isTouchedNew);
    }
    }
    

    【讨论】:

    • 您好,感谢您的意见。如果我理解正确,我认为您不应该将打印语句放在setState 中,因为您没有设置对影响任何屏幕小部件的任何数据进行更改。您可以将它放在下面的“}”之后,但既没有尝试过,又将 setState(() { isTouched=isTouchedNew; } 放回去只会阻止饼图段扩展。
    • 尝试将这一行“widget.setIsTouched(touchedIndex)”放在上面的 setState() 中。
    • 问题是函数中已经有一个setState(),所以你在setState()中使用了setState()。话虽如此,我确实尝试过,但它在设置状态下无法像您所做的那样使用此功能,但是如果您执行您所做的但没有原始@中的setState(),它也不起作用987654328@ 功能。我只是不知道该怎么办
    • 兄弟我无法正确理解它,您可以访问setIstoichex() 中的新touchedIndex 吗?你试过打印吗?
    • 是的,我试过打印它。我仍然无法访问setIsTouched() 中的新touchedIndex。基本上我仍然无法让它工作
    猜你喜欢
    • 2021-01-24
    • 2020-04-21
    • 2021-04-06
    • 1970-01-01
    • 2023-04-08
    • 2021-06-05
    • 1970-01-01
    • 2020-02-14
    • 2020-04-25
    相关资源
    最近更新 更多