I'm programming an app that displays two media streams in the same view via one horizontal listView
and one vertical listView
. I'm currently working on implementing information into the bottom listView
using some nice looking boilerplate that can be found here.
I'm new to flutter and have believe my code has gotten a little messy, in short I'm receiving the error;
flutter: The following NoSuchMethodError was thrown building Builder: flutter: The method 'loadCurrencies' was called on null. flutter: Receiver: null flutter: Tried calling: loadCurrencies()
when trying to implement code found here in the home_page_view.dart
into the aforementioned boilerplate.
This is the code I'm using to stimulate the error;
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, ], ), ); } }
This is what my simulator looks like after I've Initialised the app
Thanks for the help, and if you need any more code please let me know.
The Solution In this case, make sure you've install Android Build Tools 29.0. 0, otherwise Flutter will fail with the error above.
Null safety prevents errors that result from unintentional access of variables set to null . For example, if a method expects an integer but receives null , your app causes a runtime error. This type of error, a null dereference error, can be difficult to debug.
You have a CryptoListPresenter _presenter
but you are never initializing it. You should either be doing that when you declare it or in your initState()
(or another appropriate but called-before-you-need-it method).
One thing I find that helps is that if I know a member is functionally 'final', to actually set it to final as that way the analyzer complains that it hasn't been initialized.
EDIT:
I see diegoveloper beat me to answering this, and that the OP asked a follow up.
@Jake - it's hard for us to tell without knowing exactly what CryptoListPresenter is, but depending on what exactly CryptoListPresenter actually is, generally you'd do final CryptoListPresenter _presenter = new CryptoListPresenter(...);
, or
CryptoListPresenter _presenter; @override void initState() { _presenter = new CryptoListPresenter(...); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With