In my app I have a video running in the background.
I have a parameter page with a filepicker button which saves the path of the selected video in sharedpreferences
Future<File> _pickVideo() async {
final result = await FilePicker.platform.pickFiles(type: FileType.video);
File file = File(result!.files.single.path ?? '');
if (file != null) {
setState(() {
pickedVideo = file;
print('video $pickedVideo');
});
}
return file;}
In the video player page i retrieve the sharedpreferences path and I can display it in a Text widget
Text(selectedVideoValue ?? '',)
when I want to use it in the video player it doesn't work.
am i doing something wrong?
String? selectedVideoValue;
if (selectedVideoValue != null) {
controller = VideoPlayerController.file(File('{$selectedVideoValue}'))
..addListener(() => setState(() {}))
..initialize().then((_) {
controller.setVolume(0.0);
controller.play();
controller.setLooping(true);
setState(() {});
});
} else {
controller =
VideoPlayerController.asset("assets/movies/STYLEARCHIGRAPHIQUE.mp4")
..addListener(() => setState(() {}))
..initialize().then((_) {
controller.setVolume(0.0);
controller.play();
controller.setLooping(true);
setState(() {});
});
}
Thanks for your help
Below Code set into initState() may be working
controller = VideoPlayerController.file(File('{$selectedVideoValue}'))
..addListener(() => setState(() {}))
..initialize().then((_) {
controller.setVolume(0.0);
controller.play();
controller.setLooping(true);
setState(() {});
});
} else {
controller =
VideoPlayerController.asset("assets/movies/STYLEARCHIGRAPHIQUE.mp4")
..addListener(() => setState(() {}))
..initialize().then((_) {
controller.setVolume(0.0);
controller.play();
controller.setLooping(true);
setState(() {});
});
}```
Related
I want return a value of videoController from this function and pass it like a parameter to another. When I print value inside this function I get value as I expect but when pass it to another and print it I get null.
Future<VideoPlayerController> _startVideoPlayer() async {
VideoPlayerController vController =
VideoPlayerController.file(File(videoFile.path));
videoPlayerListener = () {
if (videoController != null && videoController.value.size != null) {
// Refreshing the state to update video player with the correct ratio.
if (mounted) setState(() {});
videoController.removeListener(videoPlayerListener);
}
};
vController.addListener(videoPlayerListener);
await vController.setLooping(true);
await vController.initialize();
await videoController?.dispose();
if (mounted) {
setState(() {
imageFile = null;
videoController = vController;
});
}
await vController.play();
return videoController;
}
Try
Future<VideoPlayerController> _startVideoPlayer() async {
VideoPlayerController vController =
VideoPlayerController.file(File(videoFile.path));
videoPlayerListener = () {
if (videoController != null && videoController.value.size != null) {
// Refreshing the state to update video player with the correct ratio.
if (mounted) setState(() {});
videoController.removeListener(videoPlayerListener);
}
return videoPlayerListener;
};
vController.addListener((){_startVideoPlayer();});
await vController.setLooping(true);
await vController.initialize();
await videoController?.dispose();
if (mounted) {
setState(() {
imageFile = null;
videoController = vController;
});
}
await vController.play();
return videoController;
By default The text to speech engine uses an async call, this causes the main Dart thread to go on with whatever line of code comes next, this leads up to another setstate() call after the TTS speak function which reverts the animation state from Speaking to Idle almost instantly.
is there any way to avoid this issue?
I want it to work as follows:
setstate(() => _animation = 'Speaking')
wait until the TTS is finished speaking
setstate(() => _animation = 'Idle')
If I'm misunderstanding something, could you please point it out? in case this is how Dart works then if you have any workarounds that'd be great.
Simplified code for inspection:
void _speak(String sentence) async {
updateRiveRoot(_animation = 'Speak');
setState(() => _isSpeaking = true);
if (!_isSpeaking) {
await tts.awaitSpeakCompletion(true);
tts.speak(sentence).then((result) {
if (result != null) {
print("getting here");// not being preinted out
setState(() => _isListening = false);
setState(() => _isSpeaking = false);
updateRiveRoot(_animation = 'Idle');
}
});
} else {
setState(() => _isSpeaking = true);
}
print("isSpeaking is $_isSpeaking and animation is $_animation");
}
I have scrolled through the TTS documentation but couldn't find useful information on the problem I'm currently facing.
try to use .then,
void _speak(String sentence) async {
if (!_isSpeaking) {
setState(() => _animation = 'Speak');
setState(() => _isSpeaking = true);
tts.speak(sentence).then((result) {
if (result != null) {
_isListening = false;
_isSpeaking = false;
setState((){});
}
});
}
} else {
setState(() => _isSpeaking = false);
}
}
I have the following in the build widget and because it's in a stream it's always calling the callback, how do I stop the stream once there is data so it only happens once. I tried to dispose of it but that did not work. I also don't have a cancel method.
// Conroller and handles the listening
void _onQRViewCreated(QRViewController controller) {
setState(() {
this.controller = controller;
});
// Might need to add onError
controller.scannedDataStream.listen((scanData) {
setState(() {
result = scanData;
widget.qrSuccess(result.code);
});
});
}
I solved this by pausing the camera here is the code
controller.scannedDataStream.listen(
(onData) {
setState(() {
controller.pauseCamera();
result = onData;
widget.qrSuccess(result.code);
print(result.code);
});
},
onError: (err) {
print('Error!');
},
cancelOnError: false,
onDone: () {
print('Done!');
},
);
Just use first property of stream
void _onQRViewCreated(QRViewController controller) async{
setState(() {
this.controller = controller;
});
final scanData = await controller.scannedDataStream.first;
controller.scannedDataStream.close();
setState(() {
result = scanData;
widget.qrSuccess(result.code);
});
}
It shows me this error.
E/flutter (22343): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
E/flutter (22343): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
E/flutter (22343): This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
#override
void initState() {
super.initState();
if(mounted){
getProfilePosts();
getFollowers();
getFollowing();
checkIfFollowing();
}
}
checkIfFollowing() async {
if(mounted){
setState(() {
_isLoading = true;
});
DocumentSnapshot doc = await followersRef
.document(widget.profileId)
.collection('userFollowers')
.document(currentUserId)
.get();
setState(() {
_isFollowing = doc.exists;
});
setState(() {
_isLoading = false;
});
}
}
getFollowers() async {
if(mounted){
setState(() {
_isLoading = true;
});
QuerySnapshot snapshot = await followersRef
.document(widget.profileId)
.collection('userFollowers')
.getDocuments();
setState(() {
followerCount = snapshot.documents.length;
});
setState(() {
_isLoading = false;
});
}
}
getFollowing() async {
if(mounted){
setState(() {
_isLoading = true;
});
QuerySnapshot snapshot = await followingRef
.document(widget.profileId)
.collection('userFollowing')
.getDocuments();
setState(() {
followingCount = snapshot.documents.length;
});
setState(() {
_isLoading = false;
});
}
}
getProfilePosts() async {
if(mounted){
setState(() {
_isLoading = true;
});
QuerySnapshot snapshot = await postsRef
.document(widget.profileId)
.collection('userPosts')
.orderBy('timestamp', descending: true)
.getDocuments();
setState(() {
postCount = snapshot.documents.length;
posts = snapshot.documents.map((doc) => Post.fromDocument(doc)).toList();
_isLoading = false;
});
}
}
Try to do this in all the setState calls, it seems you check that only once, but the following calls to setState are unprotected
if (mounted == true) {
setState(() {})
}
You can override setState to use it only if the State object is mounted on the widget tree.
#override
void setState(fn) {
if (mounted) super.setState(fn);
}
Use
if (!mounted) return;
setState(){
/* ... */
}
OR
if (mounted) {
setState(() {
/* ... */
});
}
Reference: https://stackoverflow.com/a/74744364/13431819
when i run my app in debug mode it shows me the error "type 'future' is not a subtype of type 'function'" all over the screen and also in the debug console. Can someone help me? I imagine it's a problem with async functions "reset","rateoGet" and "rateoSave" but i can't find any solution.
P.S. I've deleted part of the code because it was useless for this question.
int plus;
int min;
int per;
int div;
double val;
int gameswon =0;
int moves;
static int mosse=15;
String win = "gioca";
int games=0;
double rateo=1;
String mode;
int flag;
var timer=30;
#override
void initState() {
super.initState();
reset();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body:
MyButton(text: "$per" ,color: Colors.deepPurpleAccent, onTap: (){
setState(() {
val*=per;
});
if(widget.mode=="timermode" && flag==0){
timerceckresults();
}else if(widget.mode=="movesmode"){
checkResult();
}
},
MyBottomButton(text: "Reset",color: Colors.indigo,width:160, onTap: reset()),
),
}
checkResult() {
if(val == 101) {
print("hai vinto");
win="Hai Vinto";
setState(() {});
gameswon++;
Timer(Duration(seconds: 2), () {
reset();
});
} else {
print("ci sei quasi");
moves++;
mosse--;
win="$mosse moves left";
setState(() {});
if(moves>14){
print("hai perso coglione");
win="Hai Perso Coglione";
setState(() {});
Timer(Duration(seconds: 2), () {
reset();
});
}
}
}
timerceckresults(){
flag=1;
timer = 30;
Timer.periodic(Duration(seconds: 1), (t){
timer--;
setState(() {
win = "${timer.toString()}seconds left";
});
if(val==101){
timer=0;
}
if(timer == 0) {
t.cancel();
if(val == 101) {
win="Hai Vinto";
setState(() {});
gameswon++;
Timer(Duration(seconds: 2), () {
reset();
});
} else {
win="Hai Perso Coglione";
setState(() {});
Timer(Duration(seconds: 2), () {
reset();
});
}
}
});
static int randNum(x,y) {
var rng = new Random();
return rng.nextInt(y-x)+x;
}
reset() async{
timer=1;
plus = randNum(4, 9);
min = randNum(5, 19);
per = randNum(3, 9);
div = randNum(2, 5);
val = randNum(2, 11).toDouble();
moves = 0;
mosse=15;
if(widget.mode=="timermode"){
win="start playing";
}else{
win="$mosse moves left";
}
await rateoSave();
await rateoGet();
games++;
rateo=gameswon/(games-1);
await rateoSave();
flag=0;
setState(() {});
}
rateoSave() async {
SharedPreferences prefs=await SharedPreferences.getInstance();
await prefs.setInt("games",games);
await prefs.setInt("gameswon",gameswon);
}
rateoGet() async {
SharedPreferences prefs=await SharedPreferences.getInstance();
games=(prefs.getInt("games") ?? 0);
gameswon=(prefs.getInt("gameswon") ?? 0);
https://dart.dev/codelabs/async-await read this before you check the answer will help you alot
reset() async{
timer=1;
plus = randNum(4, 9);
min = randNum(5, 19);
per = randNum(3, 9);
div = randNum(2, 5);
val = randNum(2, 11).toDouble();
moves = 0;
mosse=15;
if(widget.mode=="timermode"){
win="start playing";
}else{
win="$mosse moves left";
}
await rateoSave();
await rateoGet();
games++;
rateo=gameswon/(games-1);
await rateoSave();
flag=0;
setState(() {});
}
Future<bool> rateoSave() {
SharedPreferences prefs= SharedPreferences.getInstance();
prefs.setInt("games",games);
prefs.setInt("gameswon",gameswon);
return true;
}
Future<bool> rateoGet() async {
SharedPreferences prefs= SharedPreferences.getInstance();
await games=(prefs.getInt("games") ?? 0);
await gameswon=(prefs.getInt("gameswon") ?? 0);
return true;
}
you are trying to get a variable from a method that returns a future. you need to add await just before you make the call to that function.
can you tell us in which line this error occurs ?
The most important thing to keep in mind is that if anything in your call-chain returns a Future, everything above it must deal with futures, either by returning the future itself (if no processing must be done), or await'ing and dealing with the returned value (but you'll still be returning a future).