【问题标题】:Flutter - The method was called on nullFlutter - 该方法在 null 上调用
【发布时间】:2019-02-02 10:30:45
【问题描述】:

我正在编写一个应用程序,该应用程序通过一个水平的listView 和一个垂直的listView 在同一视图中显示两个媒体流。我目前正在使用可以在here 找到的一些漂亮的样板将信息实现到底部listView

我是 Flutter 的新手,我相信我的代码有点乱,简而言之,我收到了错误;

flutter: The following NoSuchMethodError was thrown building Builder:
flutter: The method 'loadCurrencies' was called on null.
flutter: Receiver: null
flutter: Tried calling: loadCurrencies()

当尝试将home_page_view.dart 中的here 代码实现到上述样板文件中时。

这是我用来激发错误的代码;

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:to_be_deleted/data/crypto_data.dart';
import 'package:to_be_deleted/modules/crypto_presenter.dart';
import 'dart:async';
import 'dart:io';
import 'background.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
  title: 'Flutter Demo',
  theme: new ThemeData(
    primarySwatch: Colors.blue,
  ),
  debugShowCheckedModeBanner: false,
  home: new MyHomePage(title: 'Popular'),
);
}
}

class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);

final String title;

@override
_MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
CryptoListPresenter _presenter;
  List<Crypto> _currencies;
  bool _isLoading;
  final List<MaterialColor> _colors = [Colors.blue, Colors.indigo, Colors.red];
List<String> items = [
"Item 1",
"Item 2",
"Item 3",
"Item 4",
"Item 5",
"Item 6",
"Item 7",
"Item 8"
];



  var refreshKey = new GlobalKey<RefreshIndicatorState>();

  @override
  void initState() {
    super.initState();
    _isLoading = true;
    _presenter.loadCurrencies();
    refreshList();
  }

    Future<Null> refreshList() async {
    refreshKey.currentState?.show(atTop: false);
    await new Future.delayed(new Duration(seconds: 1));
      _presenter.loadCurrencies();
      Scaffold.of(context).showSnackBar(
            new SnackBar(
              duration: new Duration(seconds: 3),
              backgroundColor: Colors.black,
              content: new Text(
                    'Refresh available every 60 seconds',
                    textAlign: TextAlign.center,
                  ),
              ),
            );
    setState(() {
    });
    return null;
  }

@override
Widget build(BuildContext context) {
final _width = MediaQuery.of(context).size.width;
final _height = MediaQuery.of(context).size.height;

  Widget _getSubtitleText(String priceUSD, String percentageChange) {
    TextSpan priceTextWidget = new TextSpan(
        text: "\$$priceUSD\n", style: new TextStyle(color: Colors.black));
    String percentageChangeText = "1 hour: $percentageChange%";
    TextSpan percentageChangeTextWidget;

    if (double.parse(percentageChange) > 0) {
      percentageChangeTextWidget = new TextSpan(
          text: percentageChangeText,
          style: new TextStyle(color: Colors.green ));
    } else {
      percentageChangeTextWidget = new TextSpan(
          text: percentageChangeText, style: new TextStyle(color: Colors.red));
    }

    return new RichText(
        text: new TextSpan(
            children: [priceTextWidget, percentageChangeTextWidget]));
  }

  ListTile _getListItemUi(Crypto currency, MaterialColor color) {
    return new ListTile(
      leading: new Image.asset(
        "cryptoiconsBlack/"+currency.symbol.toLowerCase()+"@2x.png",
        width: 64.0,
        height: 64.0,
        ),
      title: new Text(currency.name,
          style: new TextStyle(fontWeight: FontWeight.bold)),
      subtitle:
      _getSubtitleText(currency.price_usd, currency.percent_change_1h),
      isThreeLine: true,
    );
  }

final headerList = new ListView.builder(
  itemBuilder: (context, index) {
    EdgeInsets padding = index == 0?const EdgeInsets.only(
        left: 20.0, right: 10.0, top: 4.0, bottom: 30.0):const EdgeInsets.only(
        left: 10.0, right: 10.0, top: 4.0, bottom: 30.0);

    return new Padding(
      padding: padding,
      child: new InkWell(
        onTap: () {
          print('Card selected');
        },
        child: new Container(
          decoration: new BoxDecoration(
            borderRadius: new BorderRadius.circular(10.0),
            color: Colors.lightGreen,
            boxShadow: [
              new BoxShadow(
                  color: Colors.black.withAlpha(70),
                  offset: const Offset(3.0, 10.0),
                  blurRadius: 15.0)
            ],
            image: new DecorationImage(
              image: new ExactAssetImage(
                  'assets/img_${index%items.length}.jpg'),
              fit: BoxFit.fitHeight,
            ),
          ),
        //height: 200.0,
          width: 200.0,
          child: new Stack(
            children: <Widget>[
              new Align(
                alignment: Alignment.bottomCenter,
                child: new Container(
                    decoration: new BoxDecoration(
                        color: const Color(0xFF273A48),
                        borderRadius: new BorderRadius.only(
                            bottomLeft: new Radius.circular(10.0),
                            bottomRight: new Radius.circular(10.0))),
                    height: 30.0,
                    child: new Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        new Text(
                          '${items[index%items.length]}',
                          style: new TextStyle(color: Colors.white),
                        )
                      ],
                    )),
              )
            ],
          ),
        ),
      ),
    );
  },
  scrollDirection: Axis.horizontal,
  itemCount: items.length,
);

final body = new Scaffold(
  appBar: new AppBar(
    title: new Text(widget.title),
    elevation: 0.0,
    backgroundColor: Colors.transparent,
    actions: <Widget>[
      new IconButton(icon: new Icon(Icons.shopping_cart, color: Colors.white,), onPressed: (){})
    ],
  ),
  backgroundColor: Colors.transparent,
  body: new Container(
    child: new Stack(
      children: <Widget>[
        new Padding(
          padding: new EdgeInsets.only(top: 10.0),
          child: new Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
              new Align(
                alignment: Alignment.centerLeft,
                child: new Padding(
                    padding: new EdgeInsets.only(left: 8.0),
                    child: new Text(
                      'Trending News',
                      style: new TextStyle(color: Colors.white70),
                    )),
              ),
              new Container(
                  height: 300.0, width: _width, child: headerList),
              new Expanded(child:
              ListView.builder(itemBuilder: (context, index) {
                return new ListTile(
                  title: new Column(
                    children: <Widget>[
                      new Row(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                               new Container(
                                margin: const EdgeInsets.all(10.0),
                                  child: new Column(
                                    children: <Widget>[
                                      new Flexible(
                                        child: new ListView.builder(
                                          itemCount: _currencies.length,
                                          itemBuilder: (BuildContext context, int index) {
                                            final int i = index ~/ 2;
                                            final Crypto currency = _currencies[i];
                                            final MaterialColor color = _colors[i % _colors.length];
                                            if (index.isOdd) {
                                              return new Divider(color: Colors.grey);
                                            }
                                            return _getListItemUi(currency, color);
                                          },
                                        ),
                                      )
                                    ],
                                  )
                                ),
                          new SizedBox(
                            width: 8.0,
                          ),
                          new Expanded(
                              child: new Column(
                                mainAxisAlignment:
                                MainAxisAlignment.start,
                                crossAxisAlignment:
                                CrossAxisAlignment.start,
                                children: <Widget>[
                                  new Text(
                                    'My item header',
                                    style: new TextStyle(
                                        fontSize: 14.0,
                                        color: Colors.black87,
                                        fontWeight: FontWeight.bold),
                                  ),
                                  new Text(
                                    'Item Subheader goes here\nLorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry',
                                    style: new TextStyle(
                                        fontSize: 12.0,
                                        color: Colors.black54,
                                        fontWeight: FontWeight.normal),
                                  )
                                ],
                              )),
                          new Icon(
                            Icons.shopping_cart,
                            color: const Color(0xFF273A48),
                          )
                        ],
                      ),
                      new Divider(),
                    ],
                  ),
                );
              }))
            ],
          ),
        ),
      ],
    ),
  ),
);








  return new Container(
    decoration: new BoxDecoration(
      color: const Color(0xFF273A48),
    ),
    child: new Stack(
      children: <Widget>[
        new CustomPaint(
          size: new Size(_width, _height),
          painter: new Background(),
        ),
        body,
      ],
    ),
  );
  }
}

这是我初始化应用后模拟器的样子

感谢您的帮助,如果您需要更多代码,请告诉我。

【问题讨论】:

  • 你的presenter变量永远不会被初始化
  • 如何初始化它?

标签: flutter dart


【解决方案1】:

出现这个错误的原因是你使用CryptoListPresenter _presenter没有初始化

我发现CryptoListPresenter _presenter 必须被初始化才能修复,因为_presenter.loadCurrencies() 在实例化时正在通过一个空变量;

有两种初始化方式

  1. 可以在声明期间初始化,像这样

    CryptoListPresenter _presenter = CryptoListPresenter();
    
  2. 第二个,在调用initState时对其进行初始化(并分配一些值),框架将为每个状态对象调用一次此方法。

    @override
    void initState() {
      _presenter = CryptoListPresenter(...);
    }
    

【讨论】:

【解决方案2】:

如上述答案中所述,初始化变量始终是一个好习惯,但如果您有一些不知道它应该取什么值的东西,并且您想让它保持未初始化状态,那么您必须确保你在使用它之前更新它。

例如: 假设我们有double _bmi;,你不知道它应该取什么值,所以你可以保持原样,但在使用它之前,你必须先更新它的值,比如调用一个计算BMI的函数,如下所示:

String calculateBMI (){
_bmi = weight / pow( height/100, 2);
return _bmi.toStringAsFixed(1);}

或者其他什么,我的意思是,你可以保持变量不变,但在使用它之前,请确保你已经使用你正在使用的任何方法初始化它。

【讨论】:

    【解决方案3】:

    你应该先在void initState()中声明你的方法,这样当第一次加载页面时,它会先初始化你的方法,希望对你有帮助

    【讨论】:

      【解决方案4】:

      你有一个CryptoListPresenter _presenter,但你从来没有初始化它。您应该在声明它时或在您的 initState()(或另一个适当但在需要之前调用它的方法)中这样做。

      我发现有帮助的一件事是,如果我知道一个成员在功能上是“最终的”,那么实际上将其设置为最终的,因为分析器会抱怨它尚未初始化。

      编辑:

      我看到 diegoveloper 打败了我来回答这个问题,并且 OP 要求跟进。

      @Jake - 我们很难在不知道 CryptoListPresenter 到底是什么的情况下说出来,但取决于 CryptoListPresenter 到底是什么,通常你会做final CryptoListPresenter _presenter = new CryptoListPresenter(...);,或者

      CryptoListPresenter _presenter;
      
      @override
      void initState() {
        _presenter = new CryptoListPresenter(...);
      }
      

      【讨论】:

      • 你能告诉我如何初始化它吗?我在refreshList() 中有_presenter.loadCurrencies();,但不知道该放在哪里。不要担心我对此嗤之以鼻的讽刺! :)
      • 我更新了我的答案。请注意...只是因为我不知道它需要什么参数。
      • 非常感谢,这非常有效,我在测试您的解决方案时找到了一个更短的解决方案,我设法将_presenter.loadCurrencies(); 放在我的视图小部件的开头。感谢您的帮助!
      • 我也遇到过类似的情况,我就是这样做的。 final FileStorage storage; Home({Key key, @required this.storage}) : super(key: key); 然后在 void main() 中这样调用它。 ```家:家(存储:FileStorage(),),```。这负责初始化,并摆脱了这个 NoSuchMethodError。 initState() 部分是这样的。 @override void initState() { super.initState(); widget.storage.readData().then((String value) { setState(() { state = value; }); }); }
      【解决方案5】:

      因为你的初始化错误。

      不要这样,

      MethodName _methodName;

      这样做,

      MethodName _methodName = MethodName();

      【讨论】:

      • 自从我第一次发布这篇文章以来已经一年多了,所以我现在知道不要犯这些愚蠢的错误,但感谢您的意见。希望它会帮助那些也不知道要寻找什么的人。
      • 我正在使用 StreamedList mockItems = StreamedList();,但它不起作用并显示相同的错误。
      • List 消息 = List();不工作
      • @Kamlesh 列表 消息 = [];应该工作
      • 空安全不允许您建议的解决方案。谢谢亲爱的。
      猜你喜欢
      • 2020-11-06
      • 2021-02-16
      • 2019-09-23
      • 2020-06-04
      • 2021-09-23
      • 2021-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多