Reputation: 5
I have a slider that uses a value to render himself, it start rendering after I hit a button but the first time I render it, it gives me an error and then starts working properly. This is the error:
The getter 'inSeconds' was called on null. Receiver: null Tried calling: inSeconds
This is the widget that uses the data:
child: Consumer<MyAudio>(
builder: (context, audioPlayer, child) =>
SleekCircularSlider(
appearance: CircularSliderAppearance(
customWidths: CustomSliderWidths(
progressBarWidth: 2.0,
trackWidth: 1.0,
handlerSize: 1.0,
shadowWidth: 1.0,
),
infoProperties: InfoProperties(
modifier: (value) => '',
),
customColors: CustomSliderColors(
trackColor: Colors.grey,
progressBarColor: Colors.black,
),
size: 4.0,
angleRange: 360,
startAngle: -90.0,
),
min: 0.0,
max: audioPlayer.songLength.inSeconds.toDouble(),
initialValue:
audioPlayer.position.inSeconds.toDouble(),
),
),
),
And this is the function that gives me the values songLength and position:
class MyAudio extends ChangeNotifier {
Duration songLength;
Duration position;
AudioPlayer _player = AudioPlayer();
AudioCache cache;
MyAudio() {
initAudio();
}
initAudio() {
cache = AudioCache(fixedPlayer: _player);
_player.onDurationChanged.listen((Duration d) {
songLength = d;
notifyListeners();
});
_player.onAudioPositionChanged.listen((Duration p) {
position = p;
notifyListeners();
});
I think I should use an async function, what do you think?
If you need more code here's my github repo with all the files: https://github.com/astroxd/sputofy_mobile/tree/main/sputofy_2
the slider is in /lib/miniPlayer
and the values are in /lib/model/audioPlayer
Upvotes: 0
Views: 85
Reputation: 344
The problem is that when the widget is built for first time, the audioPlayer.songLength
and audioPlayer.position
are null
despite audioPlayer
is non-null.
In this fragment of code you define a pair of listeners, but the callbacks are called after the first build.
_player.onDurationChanged.listen((Duration d) {
songLength = d;
notifyListeners();
});
_player.onAudioPositionChanged.listen((Duration p) {
position = p;
notifyListeners();
});
Then, a solution can be the following:
child: Consumer<MyAudio>(
builder: (context, audioPlayer, child) => SleekCircularSlider(
appearance: CircularSliderAppearance(
customWidths: CustomSliderWidths(
progressBarWidth: 2.0,
trackWidth: 1.0,
handlerSize: 1.0,
shadowWidth: 1.0,
),
infoProperties: InfoProperties(
modifier: (value) => '',
),
customColors: CustomSliderColors(
trackColor: Colors.grey,
progressBarColor: Colors.black,
),
size: 4.0,
angleRange: 360,
startAngle: -90.0,
),
min: 0.0,
max: audioPlayer.songLength?.inSeconds?.toDouble() ?? 0.0,
initialValue: audioPlayer.position?.inSeconds?.toDouble() ?? 0.0,
),
)
Or maybe use a loader instead.
Upvotes: 1