Flutter计算器应用调用calcBase方法触发Null异常求助
Flutter计算器应用页面传参空指针异常解决
问题描述
使用Flutter和Dart开发计算器类应用,单页面运行时可正常展示计算结果,但点击“Calculate”按钮跳转至结果页面时抛出异常:
The method 'calcBase' was called on null. Receiver: null Tried calling: calcBase()
推测是对象未初始化导致,尝试AI工具和查阅资料后仍未解决,寻求帮助。
应用结构
data_input.dart中的DataPageState类:负责存储计算所需变量,包含calcBase计算方法calculate_button.dart中的Calculate组件:触发计算并跳转至ResultPageresult_page.dart的ResultPage:用于展示计算结果
相关代码
data_input.dart
class DataPage extends StatefulWidget { const DataPage({Key? key}) : super(key: key); @override DataPageState createState() => DataPageState(); } class DataPageState extends State<DataPage> { int cost = 0; String dropDown = '48'; String user = '48'; String selected = ''; List<String> values = [ '1', '2', '3', '4', '5', '6', ]; void getDropDownItem() { setState(() { selected = dropDown; }); } // for UI var dL = 0; var wL = 0; var cC = 0; var mT = 0; // to hold base data final baseValue = const [ '1', '2', '3', '4', '5', '6', ]; //Holds base lay values at positions [0]blDL, [1]blWL, [2]blCC, [3]blMT final Map<String, List<int>> blValues = { '1': [10, 20, 30, 40], '2': [50, 60, 70, 80], '3': [90, 100, 110, 120], '4': [130, 140, 150, 160], '5': [170, 180, 190, 200], '6': [210, 220, 230, 240], }; @override Widget build(BuildContext context) { return Scaffold( body: CustomScrollView( slivers: <Widget>[ SliverAppBar( floating: true, pinned: true, expandedHeight: 200.0, centerTitle: true, title: Image.asset( 'assets/images/ppLogo.png', height: 65.0, width: 200.0, fit: BoxFit.contain, alignment: Alignment.center, ), flexibleSpace: Stack( children: [ Positioned.fill( child: Image.asset( 'assets/images/inApp.jpg', fit: BoxFit.cover, )) ], ), ), SliverToBoxAdapter( child: Container( color: Colors.black26, child: Padding( padding: const EdgeInsets.symmetric( vertical: 16.0, horizontal: 32.0, ), child: Column( children: [ Padding( padding: const EdgeInsets.only( left: 0.0, top: 8.0, right: 0.0, bottom: 8.0), child: DropdownButtonFormField( decoration: const InputDecoration( labelStyle: TextStyle( color: Colors.white70, fontSize: 24.0), labelText: 'Drop Down Values'), value: dropDown, items: values .map((String value) => DropdownMenuItem( value: value, child: Text(value), )) .toList(), onChanged: (data) => setState(() { dropDown = data!; getDropDownItem(); })), ), Padding( padding: const EdgeInsets.only( left: 0.0, top: 0.0, right: 0.0, bottom: 8.0), child: TextField( onChanged: (val) { dL = int.parse(val); }, decoration: const InputDecoration( labelText: "DL", labelStyle: TextStyle( color: Colors.white70, fontSize: 18.0, ), hintText: "Enter Your DL Value", hintStyle: TextStyle( color: Colors.lightGreen, fontSize: 10.0, ), ), textInputAction: TextInputAction.next, keyboardType: TextInputType.number, inputFormatters: <TextInputFormatter>[ FilteringTextInputFormatter.digitsOnly ], ), ), Padding( padding: const EdgeInsets.only( left: 0.0, top: 0.0, right: 0.0, bottom: 8.0), child: TextField( onChanged: (val) { wL = int.parse(val); }, decoration: const InputDecoration( labelText: "WL", labelStyle: TextStyle( color: Colors.white70, fontSize: 18.0, ), hintText: "Enter Your WL Values", hintStyle: TextStyle( color: Colors.lightGreen, fontSize: 10.0, ), ), textInputAction: TextInputAction.next, keyboardType: TextInputType.number, inputFormatters: <TextInputFormatter>[ FilteringTextInputFormatter.digitsOnly ], ), ), Padding( padding: const EdgeInsets.only( left: 0.0, top: 0.0, right: 0.0, bottom: 8.0), child: TextField( onChanged: (val) { cC = int.parse(val); }, decoration: const InputDecoration( labelText: "CC", labelStyle: TextStyle( color: Colors.white70, fontSize: 18.0, ), hintText: "Enter Your CC Value", hintStyle: TextStyle( color: Colors.lightGreen, fontSize: 10.0, ), ), textInputAction: TextInputAction.next, keyboardType: TextInputType.number, inputFormatters: <TextInputFormatter>[ FilteringTextInputFormatter.digitsOnly ], ), ), Padding( padding: const EdgeInsets.only( left: 0.0, top: 0.0, right: 0.0, bottom: 24.0), child: TextField( onChanged: (val) { mT = int.parse(val); }, decoration: const InputDecoration( labelText: "MT", labelStyle: TextStyle( color: Colors.white70, fontSize: 18.0, ), hintText: "Enter Your MT Value", hintStyle: TextStyle( color: Colors.lightGreen, fontSize: 10.0, ), ), textInputAction: TextInputAction.next, keyboardType: TextInputType.number, inputFormatters: <TextInputFormatter>[ FilteringTextInputFormatter.digitsOnly ], ), ), const Calculate(), const Padding( padding: EdgeInsets.only( left: 0.0, top: 8.0, right: 0.0, bottom: 8.0), child: Text( 'Text.', style: TextStyle( fontSize: 12.0, fontStyle: FontStyle.italic), )), ], ), ), ), ), SliverFillRemaining( child: Container(color: Colors.black26), ) ], ), bottomNavigationBar: const BottomNav(), ); } // This function calculates the base lay cost. int calcBase() { // Calculation based on the values that the user has entered in the TextFields. num cost = 0; // Get the values from the DataPage class. String dropDown = DataPageState.of(context).dropDown; var dL = DataPageState.of(context).dL; var wL = DataPageState.of(context).wL; var cC = DataPageState.of(context).cC; var mT = DataPageState.of(context).mT; // Calculate the base for each category. num dLB = blValues[dropDown]![0] * dL; num wLB = blValues[dropDown]![1] * wL; num cCB = blValues[dropDown]![2] * cC; num mTB = blValues[dropDown]![3] * mT; // Add the base for each category to get the total cost. cost = dLB + wLB + cCB + mTB; return cost.toInt(); } static of(BuildContext context) { } }
calculate_button.dart
class Calculate extends StatelessWidget { const Calculate({Key? key}) : super(key: key); Future<void> showOverlay(BuildContext context) async { OverlayState overlayState = Overlay.of(context); OverlayEntry overlayEntry = OverlayEntry( opaque: true, builder: (context) => Center(child: Image.asset("assets/images/pipeSqueak.gif"))); overlayState.insert(overlayEntry); return Future.delayed(const Duration(milliseconds: 3000), () { overlayEntry.remove(); }); } @override Widget build(BuildContext context) { return Builder( builder: (buttonContext) => ElevatedButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all<Color>(Colors.grey[600]!), foregroundColor: MaterialStateProperty.all<Color>(Colors.red[900]!), shadowColor: MaterialStateProperty.all<Color>(Colors.lightGreen[400]!), ), onPressed: () { showOverlay(context); var cost = DataPageState.of(context).calcBase(); Navigator.push( context, MaterialPageRoute( builder: (context) => ResultPage(cost: cost), ), ); }, child: const Text('Calculate'), )); } }
result_page.dart
class ResultPage extends StatelessWidget { final int cost; const ResultPage({Key? key, required this.cost}) : super(key: key); void customLaunch(command) async { if (await canLaunchUrl(command)) { await launchUrl(command); } else { throw 'Unable to complete $command'; } } @override Widget build(BuildContext context) { return Scaffold( body: CustomScrollView( slivers: <Widget>[ SliverAppBar( automaticallyImplyLeading: false, floating: false, pinned: true, expandedHeight: 100.0, title: Image.asset( 'assets/images/Blank.png', height: 0.0, width: 0.0, fit: BoxFit.contain, alignment: Alignment.bottomCenter, ), flexibleSpace: Stack( children: [ Positioned.fill( child: Image.asset('assets/images/resultAppBar.png', fit: BoxFit.cover)) ], ), ), SliverToBoxAdapter( child: Container( color: Colors.black26, child: Padding( padding: const EdgeInsets.symmetric( vertical: 16.0, horizontal: 22.0, ), child: Column( children: [ const SizedBox(height: 24.0), const Text( 'Text:', textAlign: TextAlign.justify, style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.bold), ), Text( '$cost', textAlign: TextAlign.center, style: const TextStyle( fontSize: 25.0, decoration: TextDecoration.underline, ), ), //Remaining code is text
已尝试的无效方案
修改calcBase为void方法,调整of方法写法,但仍出现空指针异常。
最终解决方法
问题根源在于成本变量的计算和传递方式,调整后代码如下:
修改后的DataPageState类
void calcBase() { setState(() { int rng = min + r.nextInt(max - min); romRandom = (rng / 100.0); final selectedBlValues = blValues[dropDown]; if (selectedBlValues != null) { rom = (dL * selectedBlValues[0] + (wL * selectedBlValues[1]) + (cC * selectedBlValues[2]) + (mT * selectedBlValues[3])); } cost = (rom * romRandom).toInt(); }); } static DataPageState of(BuildContext context) { return context.findRootAncestorStateOfType<DataPageState>()!; }
修改后的Calculate组件
DataPageState.of(context).calcBase(); var cost = DataPageState.of(context).cost;
内容的提问来源于stack exchange,提问作者DG123
相关产品推荐
相关产品推荐

