播放歌曲时报_CastError (Null check operator used on a null value)求修复
报错根因
- 双击电台卡片播放时没有给
_selectedRadio赋值,后续底部控制区域强制解包空的_selectedRadio触发_CastError - 多处直接使用
!强制解包可空变量,未做前置空校验 - 新版audioplayers的play方法不接受字符串类型参数,需要传入Source类型对象,也会触发类型转换错误
- 枚举
PlayerState的属性名在新版audioplayers中已改为小写格式,旧写法会导致匹配失败
修复后完整代码
import 'package:ai_music_player/model/radio.dart'; import 'package:ai_music_player/utils/ai_utils.dart'; import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:velocity_x/velocity_x.dart'; class HomePage extends StatefulWidget { const HomePage({Key? key}) : super(key: key); @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { List<MyRadio>? radios; MyRadio? _selectedRadio; Color? _selectedColor; bool _isPlaying = false; final AudioPlayer _audioPlayer = AudioPlayer(); @override void initState() { super.initState(); fetchRadios(); _audioPlayer.onPlayerStateChanged.listen((event) { if (event == PlayerState.playing) { _isPlaying = true; } else { _isPlaying = false; } setState(() {}); }); } fetchRadios() async { final radioJson = await rootBundle.loadString("assets/radio.json"); radios = MyRadioList.fromJson(radioJson).radios; // 初始化默认选中第一个电台,避免首次启动无选中项 if (radios?.isNotEmpty == true) { _selectedRadio = radios!.first; } setState(() {}); } playMusic(String url) { _audioPlayer.play(UrlSource(url)); if (radios?.isNotEmpty == true) { _selectedRadio = radios!.firstWhere( (element) => element.url == url, orElse: () => _selectedRadio ?? radios!.first, ); print(_selectedRadio?.name ?? '未知电台'); } setState(() {}); } @override Widget build(BuildContext context) { return Scaffold( drawer: Drawer(), body: Stack( children: [ VxAnimatedBox() .size(context.screenWidth, context.screenHeight) .withGradient( LinearGradient( colors: [AIColors.primaryColor1, AIColors.primaryColor2], begin: Alignment.topLeft, end: Alignment.bottomRight), ) .make(), AppBar( title: "AI Player".text.xl4.bold.white.make().shimmer( primaryColor: Vx.purple300, secondaryColor: Colors.white), backgroundColor: Colors.transparent, elevation: 0.0, centerTitle: true, ).h(120), radios != null ? VxSwiper.builder( itemCount: radios!.length, enlargeCenterPage: true, itemBuilder: (context, index) { final rad = radios![index]; return VxBox( child: ZStack( [ Positioned( top: 0, right: 0, child: VxBox( child: rad.lang.text.uppercase.bold.white .make() .px16(), ) .height(40) .black .alignCenter .withRounded(value: 10) .make(), ), Align( alignment: Alignment.bottomCenter, child: VStack( [ rad.name.text.xl5.white.bold.make(), 5.heightBox, rad.tagline.text.xl.white.bold.italic.make(), ], crossAlignment: CrossAlignment.center, ), ), Align( alignment: Alignment.center, child: [ const Icon( CupertinoIcons.play_circle, color: Colors.white54, size: 60, ), 10.heightBox, "DOUBLE TAB TO PLAY".text.gray300.make() ].vStack(), ), ], ), ) .clip(Clip.antiAlias) .bgImage( DecorationImage( image: NetworkImage(rad.image), fit: BoxFit.cover, colorFilter: ColorFilter.mode( Colors.black.withOpacity(0.3), BlendMode.darken), ), ) .border(color: Colors.black, width: 3) .withRounded(value: 60.0) .make() .onInkDoubleTap(() { // 复用封装好的playMusic方法,自动赋值_selectedRadio playMusic(rad.url); }); }, aspectRatio: 1.0, ).centered() : const Center( child: CircularProgressIndicator( color: Colors.white, ), ), Align( alignment: Alignment.bottomCenter, child: [ // 增加_selectedRadio非空判断,避免空解包 if (_isPlaying && _selectedRadio != null) "Playing - ${_selectedRadio!.name} FM".text.makeCentered(), Icon( _isPlaying ? CupertinoIcons.stop_circle : CupertinoIcons.play_circle, color: Colors.white, size: 60, ).onInkTap(() { if (_isPlaying) { _audioPlayer.stop(); } else { // 未选中电台时不执行播放逻辑 if (_selectedRadio != null) { _audioPlayer.play(UrlSource(_selectedRadio!.url)); } } }) ].vStack(), ).pOnly(bottom: context.percentHeight * 12) ], fit: StackFit.expand, ), ); } }
内容的提问来源于stack exchange,提问作者Rudransh Singh Mahra
相关产品推荐
相关产品推荐

