How do you get each timer count value? dart flutter - flutter

void main() {
final newTi = Get.put(NewTimer());
...
...
...: Obx((){
return Text('${newTi.count}');
// I'm trying to set a new timer and watch each of them.
// It's just 10. What should I do?
}),
}
//
//
class NewTimer extends GetxController {
RxInt count = 10.obs;
}
//
//
class TimerFunc extends GetxController {
void timeRun() {
NewTimer newTime = new NewTimer();
Timer.periodic(Duration(seconds: 1), (t) {
if (t.tick == 10) {
t.cancel();
} else {
newTime.count--;
}
});
}
}
I'm trying to set a new timer and watch each of them.
It's just 10. What should I do?
.........................................

getter? setter? in Dart.
class NewTimer {
double _count;
NewTimer(this._count);
double get count => _count;
set count(double c) => _count = c;
}
void main() {
print(NewTimer(2.0).count);
print(NewTimer(3.0).count++);
}

Related

Flutter, bug in classes

In main.dart I call Quiz's function getQuestionText and getQuestionAnswer, getQuestionText works as expected but the other doesn't work, if returns me always the first result of the list. I just placed a debugPrint() and as expected getQuestionText() prints the correct number, getQuestionAnswer() always print 0, how is that possible?
class Quiz {
int _questionNumber = 0;
List<Question> _questions = [
Question('Some cats are actually allergic to humans', true),
Question('You can lead a cow down stairs but not up stairs.', false),
];
void nextQuestion() {
if (_questionNumber < _questions.length - 1) {
_questionNumber++;
}
}
String getQuestionText() {
print('$_questionNumber'); // <-- print the correct number
return _questions[_questionNumber].questionText;
}
bool getQuestionAnswer() {
print('$_questionNumber'); // <-- always print 0
return _questions[_questionNumber].questionAnswer;
}
}
Here how I call the functions
void checkAnswer(bool userAnswer) {
bool correctAnswer = Quiz().getQuestionAnswer();
setState(() {
if (userAnswer == correctAnswer) {
// right answer
} else {
// wrong pick
);
}
quiz.nextQuestion();
});
}
The problem is that you always create a fresh instance of your class Quiz by calling bool correctAnswer = Quiz().getQuestionAnswer(); inside checkAnswer().
Try to store the Quiz instance ouside:
const myQuiz = Quiz();
void checkAnswer(bool userAnswer) {
bool correctAnswer = myQuiz.getQuestionAnswer();
setState(() {
if (userAnswer == correctAnswer) {
// right answer
} else {
// wrong pick
}
myQuiz.nextQuestion();
});
}

Unhandled Exception: Concurrent modification during iteration: Instance(length:2) of '_GrowableList'

I am using Geofire in firebase to get the location of two different users. As long as I have just 1 user it works fine but when there are more than two users online then I get the above error
Future<void> initGeoFireListener() async {
var driverLocation =
FirebaseDatabase.instance.ref().child("availableDrivers").path;
try {
Geofire.initialize(driverLocation).catchError((onError) {
print("Driver $onError");
});
Geofire.queryAtLocation(
position.latitude, position.longitude, 50)! //10 km
.listen((map) {
print("drivers map: $map");
if (map != null) {
print("Nearby Drivers: $map");
var callBack = map['callBack'];
switch (callBack) {
case Geofire.onKeyEntered:
NearByAvailableDrivers nearByAvailableDrivers =
NearByAvailableDrivers(
map['key'], map['latitude'], map['longitude']);
GeoFireAssistant.nearByAvailableDriversList
.add(nearByAvailableDrivers);
updateAvailableDriversOnMap();
// }
break;
case Geofire.onKeyExited: //when any driver is offline
GeoFireAssistant.removeDriverFromList(map['key']);
updateAvailableDriversOnMap();
// } else {
print("xxxx onKeyExited ${availableDrivers.length}");
// }
break;
case Geofire.onKeyMoved: //as driver position change
NearByAvailableDrivers nearByAvailableDrivers =
NearByAvailableDrivers(
map['key'], map['latitude'], map['longitude']);
GeoFireAssistant.updateDriverNearByLocation(
nearByAvailableDrivers);
updateAvailableDriversOnMap();
break;
case Geofire.onGeoQueryReady:
updateAvailableDriversOnMap();
// } else {
print("xxxx onGeoqueryready ${availableDrivers.length}");
// }
break;
}
} else {
print("Drivers Null");
}
// setState(() {});
}).onError((error) {
print("Drivers error $error");
});
} on PlatformException {
print("Drivers : No platformException response");
}
}
void updateAvailableDriversOnMap() async {
for (NearByAvailableDrivers driver
in GeoFireAssistant.nearByAvailableDriversList) { driverKey = driver.key; } //error triggered here
class NearByAvailableDrivers {
String? key;
double? latitude;
double? longitude;
NearByAvailableDrivers(this.key, this.latitude, this.longitude);
}
class GeoFireAssistant {
static List<NearByAvailableDrivers> nearByAvailableDriversList = []; //error
static void removeDriverFromList(String? key) {
int index =
nearByAvailableDriversList.indexWhere((element) => element.key == key);
nearByAvailableDriversList.removeAt(index);
}
static void updateDriverNearByLocation(NearByAvailableDrivers driver) {
int index = nearByAvailableDriversList
.indexWhere((element) => element.key == driver.key);
nearByAvailableDriversList[index].latitude = driver.latitude;
nearByAvailableDriversList[index].longitude = driver.longitude;
}
}
The error
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: Concurrent modification during iteration: Instance(length:2) of '_GrowableList'
I do understand I am using For loop in NearByAvailableDrivers and modifying it at the same time which could be the source of the error but I am unable to fix it.

RiverPod Maintaining selected item of list

I am new to riverpod and trying to figure out a state management issue.
I have one list, and two independent states which need access to the list. The states also need to select an element of the list and know what its index is. The list can totally change (add or remove elements) and the states need to determine if their selected element is still in the list and update the index accordingly (to 0 if it is not found)
Here is an example with Riverpod in pure dart:
import 'package:riverpod/riverpod.dart';
void main(List<String> arguments) {
final container = ProviderContainer();
List<String> names = ["Jack", "Adam", "Sally"];
container.read(nameListProvider.notifier).setNames(names);
//selectedName1 = "Adam"
//selectedIndex1 = 1
//selectedName2 = "Sally"
//selectedIndex2 = 2
names.remove('Adam');
container.read(nameListProvider.notifier).setNames(names);
// print(selectedName1) = "Jack" // set to 0 because selection was removed
// print(selectedIndex1) = 0
// print(selectedName2) = "Sally"
// print(selectedIndex2) = 1 // decrement to match Sally's new list index
}
final nameListProvider =
StateNotifierProvider<NameListNotifier, List<String>>((ref) {
return NameListNotifier();
});
class NameListNotifier extends StateNotifier<List<String>> {
NameListNotifier() : super([]);
setNames(List<String> names) {
state = names;
}
}
But I need the selected Name and Index to be Providers
Update: Here is my more elegant solution:
import 'package:riverpod/riverpod.dart';
void main(List<String> arguments) {
final container = ProviderContainer();
List<String> names = ["Jack", "Adam", "Sally"];
print(container.read(nameListProvider));
container.read(nameListProvider.notifier).setNames(names);
var first = container.read(selectionProvider(1).notifier);
first.setName(1);
print(container.read(selectionProvider(1)).name);
var second = container.read(selectionProvider(2).notifier);
second.setName(2);
print(container.read(selectionProvider(2)).name);
names.remove('Adam');
List<String> newNames = List.from(names);
container.read(nameListProvider.notifier).setNames(newNames);
print(container.read(selectionProvider(1)).name);
print(container.read(selectionProvider(1)).index);
print(container.read(selectionProvider(2)).name);
print(container.read(selectionProvider(2)).index);
print(container.read(nameListProvider));
}
final selectionProvider =
StateNotifierProvider.family<SelectionNotifier, Selection, int>(
(ref, page) {
return SelectionNotifier(ref.read);
});
class SelectionNotifier extends StateNotifier<Selection> {
Reader _read;
SelectionNotifier(this._read) : super(Selection());
update() {
final String? selectedName = state.name;
final List<String> names = _read(nameListProvider);
if (names == []) {
state = Selection();
return null;
}
if (selectedName == null) {
state = Selection(name: names[0], index: 0);
return;
}
int i = names.indexOf(selectedName);
if (i == -1) {
state = Selection(name: names[0], index: 0);
return;
}
state = Selection(name: selectedName, index: i);
return;
}
setName(int index) {
final List<String> names = _read(nameListProvider);
state = Selection(name: names[index], index: index);
}
}
final nameListProvider =
StateNotifierProvider<NameListNotifier, List<String>>((ref) {
return NameListNotifier(ref.read);
});
class NameListNotifier extends StateNotifier<List<String>> {
Reader _read;
NameListNotifier(this._read) : super([]);
setNames(List<String> names) {
state = names;
_read(selectionProvider(0).notifier).update();
_read(selectionProvider(1).notifier).update();
}
}
class Selection {
final String? name;
final int? index;
Selection({this.name, this.index});
}

Flutter : Timer.periodic running multiple times in each iteration

I am trying to make snake 2 in flutter. And I have used Timer.periodic() for game loop. And I tried specifying duration as 1 seconds. But the code inside the Timer.periodic() runs multiple times in a second. I also tried debugging (though I am terrible at that) and found that the code inside the Timer.periodic() ran multiple times without stepping out of it. Though while debugging this couild happen as the code pauses for input. But I'm not sure about anything .Here is my code -
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
class SnakePage extends StatefulWidget {
#override
_SnakePageState createState() => _SnakePageState();
}
class _SnakePageState extends State<SnakePage> {
int score = 0;
String swipe = '';
bool running = false;
int iterates = 0;
List snake = [
[
[4, 3],
1,
true
],
[
[4, 2],
1,
false
],
[
[4, 1],
1,
false
],
];
// Convert radians to degree
double radians(double degree) {
return ((degree * 180) / pi);
}
void turn(moveEvent) {
double angle = radians(moveEvent.delta.direction);
if (angle >= -45 && angle <= 45) {
this.swipe = 'Swipe Right';
} else if (angle >= 45 && angle <= 135) {
this.swipe = 'Swipe Down';
} else if (angle <= -45 && angle >= -135) {
this.swipe = 'Swipe Up';
} else {
this.swipe = 'Swipe Left';
}
}
int toIndex(coOrdinates) {
return ((coOrdinates[0] + 1) * 10) + coOrdinates[1];
}
void run() {
this.running = true;
Timer.periodic(
Duration(
milliseconds: 500,
), (timer) {
this.setState(() {
this.iterates += 1;
this.swipe = this.iterates.toString();
for (var i = 0; i < this.snake.length; i++) {
this.snake[i][0][1] += 1;
if (this.snake[i][0][1] == 10) {
this.snake[i][0][1] = 0;
}
}
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('WC'),
),
body: Listener(
onPointerMove: this.running
? (moveEvent) => this.turn(moveEvent)
: (moveEvent) => this.run(),// Where the function is being called
child: Container();
);
}
}
And please pardon me for code being a mess and not well commented.
Any Help would be appreciated!
The problem is that, every time you execute the run() method, a new timer is created and you listen for it, again. The old timer is not stopped, so it keeps firing.
The solution is, before you create a timer, cancel the previous one. Something like this:
class _SnakePageState extends State<SnakePage> {
Timer? _myTimer;
void run() {
this.running = true;
_myTimer?.cancel(); //in case we have a timer, we'll cancel it.
_myTimer = Timer.periodic(. // assing new timer to our variable.
Duration(
milliseconds: 500,
), (timer) {
this.setState(() {
this.iterates += 1;
this.swipe = this.iterates.toString();
for (var i = 0; i < this.snake.length; i++) {
this.snake[i][0][1] += 1;
if (this.snake[i][0][1] == 10) {
this.snake[i][0][1] = 0;
}
}
});
});
}
}

How to apply pagination load more function using PageController

I am working on live video streaming application with flutter. Everything is working fine except load more function. i am loading first 10 records from server and when user reach to last video i want to load more 10 records. I am using page controller to control the video pages. how can i make load more function to work. Any help would be appreciated.
Below is my page controller class
class VideoListController {
/// Construction method
VideoListController();
/// Snap to slide to realize page turning
void setPageContrller(PageController pageController) {
pageController.addListener(() {
int pageIndex = pageController.page.round();
_HomePageState home = _HomePageState();
if(pageIndex==home.videoDataList.length)
{
home.loadMore();
print("TAG loading more now");
}
var p = pageController.page;
if (p % 1 == 0) {
int target = p ~/ 1;
if (index.value == target) return;
//Play the current one, pause the others
var oldIndex = index.value;
var newIndex = target;
playerOfIndex(oldIndex).seekTo(0);
playerOfIndex(oldIndex).pause();
playerOfIndex(newIndex).start();
// carry out
index.value = target;
}
});
}
//Get specified indexçš„player
FijkPlayer playerOfIndex(int index) => playerList[index];
/// Total number of videos
int get videoCount => playerList.length;
/// Continue to add videos behind the current list and preload the cover
addVideoInfo(List<VideoModel> list) {
for (var info in list) {
playerList.add(
FijkPlayer()
..setDataSource(
Glob.ITEM_BASE_URL + info.post_video,
autoPlay: playerList.length == 0,
showCover: true,
)
..setLoop(0),
);
}
}
/// initialization
init(PageController pageController, List<VideoModel> initialList) {
addVideoInfo(initialList);
setPageContrller(pageController);
}
/// Current video sequence number
ValueNotifier<int> index = ValueNotifier<int>(0);
/// Video list
List<FijkPlayer> playerList = [];
///
FijkPlayer get currentPlayer => playerList[index.value];
bool get isPlaying => currentPlayer.state == FijkState.started;
/// Destroy all
void dispose() {
// Destroy all
for (var player in playerList) {
player.dispose();
}
playerList = [];
}
}
Below is load more function
Future<List<VideoModel>> loadMore() async {
Video menu = await getVideos();
if (menu.status == true) {
print("TAG res success is true " + menu.message);
setState(() {
videoDataList.addAll(menu.data);
start=videoDataList.length.toString();
print("TAG start " + start);
});
_videoListController.addVideoInfo(menu.data);
}
else {
print("No Data Found Paras");
}
return videoDataList;
}
Future<Video> getVideos() {
String data_type="application/x-www-form-urlencoded";
Map<String,String> headers = new Map();
headers['Content-Type'] = data_type;
return _netUtil.post(Glob.POST_LIST, body: {"count": count, "start": start,"type": type, "my_user_id": my_user_id},headers: headers).then((dynamic obj)
{
var results;
bool success = obj["status"];
print("TAG success =$success");
if (success == true)
results = Video.fromJson(obj);
else
results = Video.fromJsondata(obj);
return results;
});
}
Any help would be appreciated.
You're checking in the wrong way. You're actually checking the pageIndex value with the list size. The problem with that is index starts from 0 while length from 1 so pageIndex is never gonna match home.videoDataList.length. You have to check with home.videoDataList.length - 1
if(pageIndex == home.videoDataList.length - 1)
{
home.loadMore();
print("TAG loading more now");
}