Flutter PDF下载器报_CastError:空值使用空检查运算符求助
PDF下载器应用抛出_CastError(空检查运算符用在空值上)问题排查
问题描述
我正在开发一款PDF下载器应用,期望用户点击下载按钮时从给定链接下载PDF文件,但应用持续抛出_CastError(Null check operator used on a null value)错误,不清楚代码中何处使用了空检查运算符,请求技术帮助。
我的代码
import 'dart:isolate'; import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_downloader/flutter_downloader.dart'; import 'package:path_provider/path_provider.dart'; import 'dart:io'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await FlutterDownloader.initialize(); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int _counter = 0; void _downloadFile() async { if (FlutterDownloader.initialize() == true) { final baseStorage = await getExternalStorageDirectory(); if (baseStorage != null) { final id = FlutterDownloader.enqueue( url: 'https://drive.google.com/uc?export=download&id=1lJe77StiP9XU05l5N1TpFHYYZfdrPHYG', savedDir: baseStorage.path, fileName: 'Jony.pdf'); } } } ReceivePort receivePort = ReceivePort(); int progress = 0; downloaderCallback(id, status, progress) { var sendPort = IsolateNameServer.lookupPortByName('pdfdownloadId'); if (sendPort != null) { sendPort.send(progress); } } @override void initState() { IsolateNameServer.registerPortWithName( receivePort.sendPort, 'pdfdownloadId'); FlutterDownloader.registerCallback(downloaderCallback); receivePort.listen((message) { setState(() { progress = message; }); }); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'Click To Download', ), Text( '$progress', style: Theme.of(context).textTheme.headline4, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _downloadFile, tooltip: 'Click', child: const Icon(Icons.add), ), ); } }
错误信息
The following _CastError was thrown building Builder: Null check operator used on a null value The relevant error-causing widget was MaterialApp package:flutter_application_downloader/main.dart:21 When the exception was thrown, this was the stack #0 FlutterDownloader.registerCallback package:flutter_downloader/src/downloader.dart:397 #1 _MyHomePageState.initState package:flutter_application_downloader/main.dart:94 #2 StatefulElement._firstBuild package:flutter/…/widgets/framework.dart:4893 #3 ComponentElement.mount package:flutter/…/widgets/framework.dart:4729 ... Normal element mounting (171 frames) #174 Element.inflateWidget package:flutter/…/widgets/framework.dart:3790 #175 MultiChildRenderObjectElement.inflateWidget package:flutter/…/widgets/framework.dart:6422 #176 MultiChildRenderObjectElement.mount package:flutter/…/widgets/framework.dart:6433 ... Normal element mounting (377 frames) #553 Element.inflateWidget package:flutter/…/widgets/framework.dart:3790 #554 Element.updateChild package:flutter/…/widgets/framework.dart:3540 #555 RenderObjectToWidgetElement._rebuild package:flutter/…/widgets/binding.dart:1198 #556 RenderObjectToWidgetElement.mount package:flutter/…/widgets/binding.dart:1167 #557 RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> package:flutter/…/widgets/binding.dart:1112 #558 BuildOwner.buildScope package:flutter/…/widgets/framework.dart:2600 #559 RenderObjectToWidgetAdapter.attachToRenderTree package:flutter/…/widgets/binding.dart:1111 #560 WidgetsBinding.attachRootWidget package:flutter/…/widgets/binding.dart:944 #561 WidgetsBinding.scheduleAttachRootWidget.<anonymous closure> package:flutter/…/widgets/binding.dart:924 (elided 11 frames from class _RawReceivePortImpl, class _Timer, dart:async, and dart:async-patch)
问题原因及修复方案
核心问题
错误栈指向FlutterDownloader.registerCallback方法,问题出在你注册的downloaderCallback是_MyHomePageState类的成员函数。flutter_downloader插件要求下载回调必须是全局顶级函数或者静态函数,不能是类的实例成员函数,否则插件内部无法正确获取函数引用,导致空值转换错误。
修复步骤
将回调改为顶级函数
把downloaderCallback移出_MyHomePageState类,放在文件最外层:// 顶级函数,放在import语句下方 void downloaderCallback(id, status, progress) { var sendPort = IsolateNameServer.lookupPortByName('pdfdownloadId'); if (sendPort != null) { sendPort.send(progress); } }同时删除
_MyHomePageState类内的downloaderCallback定义。移除重复的初始化调用
_downloadFile函数里重复调用了FlutterDownloader.initialize(),而main函数中已经完成初始化,直接删除这部分判断:void _downloadFile() async { final baseStorage = await getExternalStorageDirectory(); if (baseStorage != null) { final id = FlutterDownloader.enqueue( url: 'https://drive.google.com/uc?export=download&id=1lJe77StiP9XU05l5N1TpFHYYZfdrPHYG', savedDir: baseStorage.path, fileName: 'Jony.pdf'); } }
修复后的完整代码
import 'dart:isolate'; import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_downloader/flutter_downloader.dart'; import 'package:path_provider/path_provider.dart'; import 'dart:io'; // 顶级下载回调函数 void downloaderCallback(id, status, progress) { var sendPort = IsolateNameServer.lookupPortByName('pdfdownloadId'); if (sendPort != null) { sendPort.send(progress); } } void main() async { WidgetsFlutterBinding.ensureInitialized(); await FlutterDownloader.initialize(); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int _counter = 0; void _downloadFile() async { final baseStorage = await getExternalStorageDirectory(); if (baseStorage != null) { final id = FlutterDownloader.enqueue( url: 'https://drive.google.com/uc?export=download&id=1lJe77StiP9XU05l5N1TpFHYYZfdrPHYG', savedDir: baseStorage.path, fileName: 'Jony.pdf'); } } ReceivePort receivePort = ReceivePort(); int progress = 0; @override void initState() { IsolateNameServer.registerPortWithName( receivePort.sendPort, 'pdfdownloadId'); FlutterDownloader.registerCallback(downloaderCallback); receivePort.listen((message) { setState(() { progress = message; }); }); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ const Text( 'Click To Download', ), Text( '$progress', style: Theme.of(context).textTheme.headline4, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _downloadFile, tooltip: 'Click', child: const Icon(Icons.add), ), ); } }
内容的提问来源于stack exchange,提问作者Noob Coder
相关产品推荐
相关产品推荐

