Navigation does not reload instantly on Dart/ Flutter - flutter

I am working on this navigation that is a list but it is very inconstant in refreshing. Sometimes it refreshes and appears the new button, and other times it does not show the new button. Have you had this problem before.
This is my page showing the routers list and the pages list:
class RouterTabletPage extends StatefulWidget { // ignore: must_be_immutable
BuildContext? context;
RouterTabletPage({Key? key}) : super(key: key);
#override
_RouterTabletPageState createState() => _RouterTabletPageState();
}
class _RouterTabletPageState extends State<RouterTabletPage> with SingleTickerProviderStateMixin {
final NavigationController _navigationController = IoC.get<NavigationController>()!;
final TopBarWidgetController _topBarController = IoC.get<TopBarWidgetController>()!;
final TerminalLockController _terminalLockController = IoC.get<TerminalLockController>()!;
final PreAlarmController _preAlarmController = IoC.get<PreAlarmController>()!;
final UpdateUiService _updateUiService = IoC.get<UpdateUiService>()!;
PageController? _pageViewController;
#override
initState() {
super.initState();
WidgetsBinding.instance!.addPostFrameCallback((_) async {
await _navigationController.initRoutes();
_navigationController.pageViewController = PageController(initialPage: _navigationController.menuSelectedIndex);
_pageViewController = _navigationController.pageController;
await _navigationController.getTabs(_navigationController.menuSelectedIndex);
await _navigationController.setListenerPage();
_topBarController.initTopBar();
await _navigationController.refreshCycleBtn();
});
}
registerContext() {
widget.context = context;
_terminalLockController.registerContext(context);
_preAlarmController.registerContext(context);
_updateUiService.registerContext(context);
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
registerContext();
return Observer(
builder: (_) {
return Scaffold(
appBar: _topBarController.topBarWidget,
backgroundColor: Theme.of(context).primaryColor,
body: Container(
color: Theme.of(context).primaryColor,
margin: const EdgeInsets.all(0.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
width: 60,
margin: const EdgeInsets.only(top: 0.0),
color: Theme.of(context).primaryColor,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.max,
children: _navigationController.tabs,
),
),
Expanded(
child: Container(
color: Theme.of(context).backgroundColor,
child: PageView(
scrollDirection: Axis.vertical,
controller: _pageViewController,
children: _navigationController.pages,
),
And this is my controller:
#observable
Map<num, PageWithRouter> routers = {};
#observable
String router2 = "";
#observable
int menuSelectedIndex = 0;
#observable
String preloader = "";
#observable
Object? arguments;
#observable
List<Widget> pages = [];
#observable
PageController? pageController;
#observable
List<Widget> tabs = [];
String pathPage = "";
#observable
bool cycleEnable = true;
#observable
bool isCycleStarted = false;
#observable
BuildContext? context;
set pageViewController(PageController _pageController) =>
pageController = _pageController;
#action
Future setRouter(String path) async {
initRoutes();
if (router2 != path) {
pathPage = path;
if (path != pathSplashScreen && path != "") router2 = path;
if (router2 != pathRegister) {
await _treatAuth().then((value) async {
if (!value) {
setMenuSelectedByPath(path);
await initPages();
}
});
}
}
}
#action
Future refreshCurrentPage(List<String> path) async {
if (path.contains(router2)) {
await _treatAuth().then((value) async {
if (!value) {
await initPages();
}
});
}
}
#action
setRouterByHomePage(String path) async {
await setRouter(path);
// log('path'+path);
pageController!.jumpToPage(menuSelectedIndex);
}
#action
Future<void> setRouterByIndex(int index) async {
menuSelectedIndex = index;
String _router = routers[menuSelectedIndex]?.defaultRouter ?? " ";
if (_router != router2) {
await setRouter(_router);
}
}
#action
setArguments(Object? obj) {
arguments = obj;
}
#action
setCycleEnable(bool enable) async{
cycleEnable = enable;
log('noaction'+cycleEnable.toString());
}
#action
setCycleStarted(bool started) {
isCycleStarted = started;
}
#action
setMenuSelectedIndex(int index) {
menuSelectedIndex = index;
}
#action
Widget getByIndex(int index) {
return routers[index]?.page ?? const SizedBox.shrink();
}
#action
Future<Widget> getPage(String router, int pageIdentify) async {
if (pageIdentify != menuSelectedIndex) {
return getByIndex(pageIdentify);
}
for (var item in routers.values) {
if (item.routers.any((r) => r == router) ||
(router == "" && item.defaultRouter == pathHome)) {
item.page = _createPageByRouter(router);
return _createPageByRouter(router);
// TODO: strange behaviour where returning item.page is identified as Widget?
}
}
return const SizedBox.shrink();
}
#action
Widget _createPageByRouter(String router) {
bool isTablet = DeviceType.get().isTablet!;
Widget page = const SizedBox.shrink();
bool isShowSubMenu = true;
log('router'+router);
switch (router) {
case '':
case pathHome:
page = isTablet
? const HomeTabletPage(title: "Home")
: const HomePhonePage(title: "Home");
if (isTablet) isShowSubMenu = false;
break;
case pathMessageReceived:
page = isTablet
? MessageListTabletPage(type: 1)
: MessageListPhonePage(type: 1);
break;
case pathMessageSend:
page = isTablet
? MessageListTabletPage(type: 0)
: MessageListPhonePage(type: 0);
break;
case pathInformation:
page = isTablet ? const InformationTabletPage() : const InformationPhonePage();
break;
case pathExternalDevice:
page =
isTablet ? const ExternalDeviceTabletPage() : const ExternalDevicePhonePage();
break;
case pathErrorCode:
page = isTablet ? const ErrorCodeTabletPage() : const ErrorCodePhonePage();
break;
case pathSetting:
page = isTablet
? SettingTabletPage(title: "Configurações", defaultPage: true)
: SettingPhonePage(title: "Configurações", defaultPage: true);
break;
case pathSettingUnitConfig:
page = isTablet
? SettingTabletPage(title: "Configurações", defaultPage: false)
: SettingPhonePage(title: "Configurações", defaultPage: false);
break;
case pathOperationCycle:
if (isTablet) {
return const OperationCycleMasterTablet();
} else {
if (isCycleStarted) {
page = const OperationCyclePhonePage();
} else {
page = const OperationCycleHomePhonePage();
}
}
if (isTablet) isShowSubMenu = false;
break;
default:
page = const SizedBox.shrink();
break;
}
if (isShowSubMenu && isTablet) {
return Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
IoC.get<SubMenu>()!,
Expanded(
child: page,
),
],
);
}
return page;
}
#action
Future initPages() async {
initRoutes();
pages = [];
for (final key in routers.keys) {
if (routers[key]!.defaultRouter ==
NavigationControllerBase.pathOperationCycle &&
cycleEnable == false) {
setMenuSelectedIndex(0);
setRouterByHomePage(pathHome);
}
final page = await getPage(router2, key as int);
pages.add(page);
log('initPages'+ pages.toString());
}
}
Future<bool> _treatAuth() async {
final authStatusService = IoC.get<AuthStatusService>()!;
final authStatus = await authStatusService.syncData();
if (authStatus != null && authStatus.requireLogin) {
pathPage = pathAuthentication;
router2 = pathAuthentication;
IoC.get<NavigationService>()!.navigateWithoutHistory(pathAuthentication);
return true;
}
return false;
}
#action
Future initRoutes() async {
if (DeviceType.get().isPhone!) {
routers = <num, PageWithRouter>{
0: PageWithRouter([pathHome], null),
1: PageWithRouter([pathInformation, pathExternalDevice], null),
2: PageWithRouter([pathErrorCode], null),
3: PageWithRouter([pathSetting, pathSettingUnitConfig], null),
};
if (cycleEnable) {
routers.addAll({
4: PageWithRouter([pathOperationCycle], null),
5: PageWithRouter([pathMessageReceived, pathMessageSend], null),
});
} else {
routers.addAll({
4: PageWithRouter([pathMessageReceived, pathMessageSend], null),
});
}
} else {
routers = <num, PageWithRouter>{
0: PageWithRouter([pathHome], null),
1: PageWithRouter([pathMessageReceived, pathMessageSend], null),
2: PageWithRouter([pathInformation, pathExternalDevice], null),
3: PageWithRouter([pathErrorCode], null),
4: PageWithRouter([pathSetting, pathSettingUnitConfig], null),
};
if (cycleEnable == true) {
routers.addAll({
5: PageWithRouter([pathOperationCycle], null)
});
log('initRoutes'+routers.toString());
}
}
}
#action
Future refreshCycleBtn() async {
tabs = [];
if (DeviceType.get().isPhone!) {
tabs = List.from(tabs..addAll(await getTabsPhone(menuSelectedIndex)));
} else {
tabs = List.from(tabs..addAll(await getTabs(menuSelectedIndex)));
log('tabs'+tabs.toString());
}
await initRoutes();
await _verifyOperationCycleEnabled();
if (cycleEnable == false) {
if (menuSelectedIndex > routers.length - 1) {
await setRouterByIndex(0);
pageController!.jumpToPage(0);
} else {
await initPages();
}
} else {
await initPages();
pages = [];
List<Widget> newPages = [];
for (final key in routers.keys) {
final page = await getPage(router2, key as int);
newPages.add(page);
pages = List.from(pages..addAll(newPages));
}
if (menuSelectedIndex > routers.length - 1) {
await setRouterByIndex(0);
} else {
await initRoutes();
await initPages();
}
}
}
Future<List<Widget>> getTabs(int index) async {
List<Widget> newTabs = [];
//await _menuIconsController.refreshAllBadge();
for (final key in routers.keys) {
if (routers[key]!.defaultRouter ==
NavigationControllerBase.pathOperationCycle && cycleEnable == false) {
continue;
}
newTabs.add(
SizedBox(
height: 70,
child: TextButton(
style: TextButton.styleFrom(
backgroundColor: index == key ? AppTheme.theme.colorScheme.secondary : Colors.transparent,
shape: const ContinuousRectangleBorder(
borderRadius: BorderRadius.all(Radius.zero),
),
),
child: _getTabIcon(routers[key]!.defaultRouter),
onPressed: () async {
await setRouterByIndex(key as int);
pageController!.jumpToPage(key);
},
),
),
);
}
tabs = [];
tabs = List.from(tabs..addAll(newTabs));
log('newtabs'+newTabs.toString());
return newTabs;
}
Widget _getTabIcon(String router) { // os cases com icons
switch (router) {
case '': //setado para home
return const Icon(
Icons.home,
color: Colors.white,
size: 30,
);
case NavigationControllerBase.pathHome:
return const Icon(
Icons.home,
key: Key('btn_home_page'),
color: Colors.white,
size: 30,
);
case NavigationControllerBase.pathMessageReceived:
var icon = const Icon(
Icons.mail,
key: Key('btn_message_page'),
color: Colors.white,
size: 30,
);
return Observer(builder: (_) {
if (_menuIconsController.countMessages == 0) return icon;
return Badge(
badgeContent: Text(
_menuIconsController.countMessages.toString(),
style: const TextStyle(
color: Colors.white,
),
),
child: icon,
);
});
case NavigationControllerBase.pathInformation:
return const Icon(
Icons.info,
key: Key('btn_information_page'),
color: Colors.white,
size: 30,
);
case NavigationControllerBase.pathErrorCode:
var icon = const Icon(
Icons.warning,
key: Key('btn_erro_code_page'),
color: Colors.white,
);
return Observer(builder: (_) {
if (_menuIconsController.countUccErrors == 0) return icon;
return Badge(
badgeContent: Text(
_menuIconsController.countUccErrors.toString(),
style: const TextStyle(
color: Colors.white,
),
),
child: icon,
);
});
case NavigationControllerBase.pathSetting:
var icon = const Icon(
Icons.settings,
key: Key('btn_setting_page'),
color: Colors.white,
size: 30,
);
if (!_menuIconsController.showBadgetSetting!) return icon;
return Observer(builder: (_) {
return Badge(
badgeContent: const Padding(
padding: EdgeInsets.all(2.0),
child: Text(
"!",
style: TextStyle(
color: Colors.white,
),
),
),
child: icon,
);
});
case NavigationControllerBase.pathOperationCycle:
return const Icon(
MtfIcons.operationalCycleHomeMenu,
key: Key('btn_operation_cycle'),
color: Colors.white,
size: 30,
);
default:
return const SizedBox.shrink();
}
}
Future<List<Widget>> getTabsPhone(int index) async {
List<Widget> newTabs = [];
//await _menuIconsController.refreshAllBadge();
for (final key in routers.keys) {
if (routers[key]!.defaultRouter ==
NavigationControllerBase.pathOperationCycle &&
cycleEnable == false) {
continue;
}
newTabs.add(
Expanded(
child: TextButton(
style: TextButton.styleFrom(
primary: index == key ? AppTheme.theme.colorScheme.secondary : Colors.transparent,
),
onPressed: () async {
await setRouterByIndex(key as int);
pageController!.jumpToPage(key);
},
child: _getTabIcon(routers[key]!.defaultRouter),
),
),
);
}
tabs = [];
tabs = List.from(tabs..addAll(newTabs));
return newTabs;
}
Future setListenerPage() async {
// TODO: refactor this lambda;
var listener = () async { // ignore: prefer_function_declarations_over_variables
if (DeviceType.get().isPhone!) {
await getTabsPhone(menuSelectedIndex);
} else {
await getTabs(menuSelectedIndex);
}
double page = pageController!.page!;
await setRouterByIndex(page.round());
};
pageController!.removeListener(listener);
pageController!.addListener(listener);
}
void setMenuSelectedByPath(String? path) { //init menuSeletecteIndex =id
routers.forEach((id, page) {
if (page.routers.any((r) => r == path)) {
menuSelectedIndex = id as int;
}
});
}
Future _verifyOperationCycleEnabled() async { //setCycleEnable true || false
final _operationCycleService = IoC.get<OperationCycleService>()!;
final operationCycle = await _operationCycleService.syncData();
if (operationCycle == null) {
setCycleEnable(false);
} else {
setCycleEnable(true);
}
}
}
class PageWithRouter {
List<String> routers;
Widget? page;
String get defaultRouter => routers.first;
PageWithRouter(this.routers, this.page);
}
I have already tried changing WidgetsBinding to Future.delay and tried initiating different ways inside refreshCycleBtn().

Related

When I am Trying To load Json data from local file using futurebuilder in flutter it Shows a error type Null is Not a subtype of String

import 'dart:convert';
import 'dart:math';
import "dart:async";
import 'package:flutter/material.dart';
import 'package:quizapp/style.dart';
class loadjson extends StatelessWidget {
String Name = "";
loadjson(this.Name);
String assetload = "";
setasset(){
if(Name == "Python"){
assetload = "assets/python.json";
}
else if(Name == "Java"){
assetload = "assets/java.json";
}
else if(Name == "C++"){
assetload = "assets/cpp.json";
}
else if(Name == "C"){
assetload = "assets/c.json";
}
else if(Name == "Javascript"){
assetload = "assets/js.json";
}
else if(Name == "Linux"){
assetload = "assets/linux.json";
}
else{
assetload = "assets/aws.json";
}
}
#override
Widget build(BuildContext context) {
setasset();
return FutureBuilder(
future: DefaultAssetBundle.of(context).loadString(assetload, cache: false),
builder: (context, snapshot){
List mydata = json.decode(snapshot.data.toString());
// ignore: unnecessary_null_comparison
if(mydata == null){
return Scaffold(
body: Center(
child: Text("Loading....",style: TextStyle(fontFamily: "Sweet Husky ", fontWeight: FontWeight.w700, fontSize: 20.0),),
),
);
}
else{
return quiz(mydata: mydata);
}
},
);
}
}
class quiz extends StatefulWidget {
final List mydata;
const quiz({Key? key, required this.mydata}) : super(key: key);
#override
// ignore: no_logic_in_create_state
State<quiz> createState() => _quizState(mydata);
}
class _quizState extends State<quiz> {
final List mydata;
_quizState(this.mydata);
Color Colortoshow = Apppstyle.acent;
Color right = Apppstyle.right;
Color wrong = Apppstyle.wrong;
int marks = 0;
bool disableAnswer = false;
int j = 1;
int i =0;
int timer = 30;
String Showtimer = "30";
var random_array;
Map<String, Color> btncolor = {
"a": Apppstyle.acent,
"b": Apppstyle.acent,
"c": Apppstyle.acent,
"d": Apppstyle.acent
};
#override
void initState() {
Startimer();
genrandomarray();
// TODO: implement initState
super.initState();
}
bool canceltime = false;
genrandomarray(){
var distinids = [];
var rand = new Random();
for(int i =0; ;){
distinids.add(rand.nextInt(10));
random_array = distinids.toSet().toList();
if(random_array.length < 10){
continue;
}
else{
break;
}
}
print(random_array);
}
void Startimer() async{
const onsec = Duration(seconds: 1);
Timer.periodic(onsec, (Timer T) {
setState(() {
if(timer < 1){
T.cancel();
nextquestion();
}
else if(canceltime == true){
timer = timer - 1;
}
Showtimer = timer.toString();
});
});
}
void nextquestion(){
canceltime = false;
timer = 30;
setState(() {
if(j < 10){
i = random_array[i];
j++;
}
else{
btncolor["a"] = Apppstyle.acent;
btncolor["b"] = Apppstyle.acent;
btncolor["c"] = Apppstyle.acent;
btncolor["d"] = Apppstyle.acent;
disableAnswer = false;
Startimer();
}
});
}
void Checkanswer(String K){
if(mydata[2][i.toString()] == mydata[1][i.toString()][K]){
marks = marks+5;
Colortoshow = right;
}
else{
Colortoshow = wrong;
}
setState(() {
btncolor[K] = Colortoshow;
canceltime = true;
disableAnswer = false;
});
Timer(Duration(seconds: 3), nextquestion);
}
#override
void setState(fn){
if(mounted){
super.setState(() {
fn;
});
}
}
Widget Choicebutton(String K){
return Padding(
padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 10.0),
child: MaterialButton(
onPressed:() => Checkanswer(K),
color:btncolor[K],
child: Text(mydata[i][i.toString()][K], style: TextStyle(fontFamily: "Eriega", fontSize: 18.0), maxLines: 1,),
minWidth: 200.0,
height: 45.0,
splashColor: Apppstyle.splash,
highlightColor: Apppstyle.splash,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
),
);
}
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop:() async => false,
child: Scaffold(
body: Column(
children: [
Expanded(
flex: 3,
child: Container(
padding: EdgeInsets.all(15.0),
alignment: Alignment.bottomLeft,
child: Text(mydata[0][i.toString()],style: TextStyle(fontFamily: " Eriega", fontSize: 16.0),),
),
),
Expanded(
flex:6,
child: AbsorbPointer(
absorbing: disableAnswer,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Choicebutton('a'),
Choicebutton('b'),
Choicebutton('c'),
Choicebutton('d'),
],
),
),
)
],
),
)
);
}
}
and the code For Appstyle class
import 'package:flutter/Material.dart';
class Apppstyle{
static Color cardColor = Color(0xFF80DEEA);
static Color right = Color(0xFF2E7D32);
static Color wrong = Color(0xFFF44336);
static Color acent = Color(0xFF18FFFF);
static Color splash = Color(0xFF4DD0E1);
}
Error Shown while building
type 'Null' is not a subtype of 'String'
The relevant error-causing widget was quiz
I am building a multipage quiz App using json file stored locally
but when I try to load json file using futurebuilder in flutter
It Shows error while type Null is not a subtype of Type String
The relevant error-causing widget was quiz i am trying to display the json data when the
user tab a Inkwell

How to reload only a page that is a part of a bottownavigationbar in flutter

Hi i have a riveanimation that changes flower when the user has checkin, however the page of the animation would not change state once build as it is in a bottomnavigationbar. Is there anyway to reload the page to change the state of the animation. I only want to reload only one page and maintain the others.
This is the animation picture, it should change the leaf to green
here is my bottomnavigationbar page
class bottomnavbar extends StatefulWidget {
const bottomnavbar ({Key? key}) : super(key: key);
#override
_bottomnavbarState createState() => _bottomnavbarState();
}
class _bottomnavbarState extends State<bottomnavbar> {
double screenHeight = 0;
double screenWidth = 0;
String currentDate = DateFormat('yyyy-MM-dd').format(DateTime.now());
Color primary = const Color(0xffeef444c);
int currentIndex = 0;
List<IconData> navigationIcons = [
FontAwesomeIcons.personPraying,
FontAwesomeIcons.leaf,
FontAwesomeIcons.dice,
FontAwesomeIcons.person,
];
#override
Widget build(BuildContext context) {
screenHeight = MediaQuery.of(context).size.height;
screenWidth = MediaQuery.of(context).size.width;
print("Current save date is ${Provider.of<checkinlist>(context, listen: false).checkDate()}");
if( Provider.of<checkinlist>(context, listen: false).checkDate() == 'not set'){
Provider.of<checkinlist>(context, listen: false).saveDatenow();
}
else if (Provider.of<checkinlist>(context, listen: false).checkDate() != currentDate ){
Provider.of<checkinlist>(context, listen: false).overwriteSaveDate();
Provider.of<checkinlist>(context, listen: false).dailyreset();
}
else if (Provider.of<checkinlist>(context, listen: false).checkDate() == currentDate ){
}
return Scaffold(
backgroundColor: Colors.blueGrey[900],
body: IndexedStack(
index: currentIndex,
children: const [
mainmenu(),
FlowerGarden(),
Gamespage(),
ProfilePage(),
],
),
bottomNavigationBar: Container(
height: 70,
margin: const EdgeInsets.only(
left: 12,
right: 12,
bottom: 24,
),
decoration: const BoxDecoration(
color: Colors.lime,
borderRadius: BorderRadius.all(Radius.circular(40)),
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 10,
offset: Offset(2, 2),
),
],
),
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(40)),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
for(int i = 0; i < navigationIcons.length; i++)...<Expanded>{
Expanded(
child: GestureDetector(
onTap: () {
setState(() {
currentIndex = i;
});
},
child: Container(
height: screenHeight,
width: screenWidth,
color: Colors.deepPurple[900],
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
navigationIcons[i],
color: i == currentIndex ? primary : Colors.white60,
size: i == currentIndex ? 30 : 26,
),
i == currentIndex ? Container(
margin: const EdgeInsets.only(top: 6),
height: 3,
width: 22,
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(40)),
color: primary,
),
) : const SizedBox(),
],
),
),
),
),
),
}
],
),
),
),
);
}
}
And this is my riveanimation page
class FlowerGarden extends StatefulWidget{
const FlowerGarden({Key? key,
}) : super(key: key);
#override
_SimpleFlowerGardenState createState() => _SimpleFlowerGardenState();
}
final myCoordinates = Coordinates(3.139003, 101.686855);
// Replace with your own location lat, lng.
final params = CalculationMethod.karachi.getParameters();
final prayerTimes = PrayerTimes.today(myCoordinates, params);
class _SimpleFlowerGardenState extends State<FlowerGarden>{
SMITrigger? _SubuhEarly;
SMITrigger? _SubuhLate;
SMITrigger? _ZohorEarly;
SMITrigger? _ZohorLate;
SMITrigger? _AsarEarly;
SMITrigger? _AsarLate;
SMITrigger? _MaghribEarly;
SMITrigger? _MaghribLate;
SMITrigger? _IsyakEarly;
SMITrigger? _IsyakLate;
SMITrigger? _solatPerfect;
SMITrigger? _solatImperfect;
Artboard? _riveArtboard;
String? message;
#override
void initState() {
super.initState();
// Load the animation file from the bundle, note that you could also
// download this. The RiveFile just expects a list of bytes.
rootBundle.load('android/assets/lotus.riv').then(
(data) async {
// Load the RiveFile from the binary data.
final file = RiveFile.import(data);
// The artboard is the root of the animation and gets drawn in the
// Rive widget.
final artboard = file.mainArtboard;
var controller =
StateMachineController.fromArtboard(artboard, 'State Machine ',onStateChange: _onStateChange);
if (controller != null) {
artboard.addController(controller);
_SubuhEarly = controller.findInput<bool>('Subuh Early') as SMITrigger;
_SubuhLate = controller.findInput<bool>('Subuh Late') as SMITrigger;
_ZohorEarly = controller.findInput<bool>('Zohor Early') as SMITrigger;
_ZohorLate = controller.findInput<bool>('Zohor late') as SMITrigger;
_AsarEarly = controller.findInput<bool>('Asar Early') as SMITrigger;
_AsarLate = controller.findInput<bool>('Asar Late') as SMITrigger;
_MaghribEarly = controller.findInput<bool>('Maghrib early') as SMITrigger;
_MaghribLate = controller.findInput<bool>('Maghrib late') as SMITrigger;
_IsyakEarly = controller.findInput<bool>('Ishak early') as SMITrigger;
_IsyakLate = controller.findInput<bool>('Ishak late') as SMITrigger;
_solatPerfect = controller.findInput<bool>('Solat Perfect') as SMITrigger;
_solatImperfect = controller.findInput<bool>('Solat Imperfect') as SMITrigger;
}
setState(() => _riveArtboard = artboard);
},
);
}
void _onStateChange(
String stateMachineName,
String stateName,
) =>
setState(
() => print('State Changed in $stateMachineName to $stateName') ,
);
void flowercheck(){
if (Provider.of<checkinlist>(context, listen: false).getSubuh() == 2){
_solatImperfect?.fire();
}
else if (Provider.of<checkinlist>(context, listen: false).getZohor() == 2){
_solatImperfect?.fire();
}
else if (Provider.of<checkinlist>(context, listen: false).getAsar() == 2){
_solatImperfect?.fire();
}
else if (Provider.of<checkinlist>(context, listen: false).getMaghrib() == 2){
_solatImperfect?.fire();
}
else if (Provider.of<checkinlist>(context, listen: false).getIsyak() == 2){
_solatImperfect?.fire();
}
else {
_solatPerfect?.fire();
}
}
void leafcheck(){
int subuh = Provider.of<checkinlist>(context, listen: false).getSubuh();
int zohor = Provider.of<checkinlist>(context, listen: false).getZohor();
int asar = Provider.of<checkinlist>(context, listen: false).getAsar();
int maghrib = Provider.of<checkinlist>(context, listen: false).getMaghrib();
int isyak = Provider.of<checkinlist>(context, listen: false).getIsyak();
double health = Provider.of<solatPoints>(context, listen: false).getHealth();
switch(subuh){
case 1:
_SubuhEarly?.fire();
break;
case 2:
_SubuhLate?.fire();
if (health > 5) {
Provider.of<solatPoints>(context, listen: false).decreasehealth();
}
break;
}
switch(zohor){
case 1:
_ZohorEarly?.fire();
break;
case 2:
_ZohorLate?.fire();
if (health > 5) {
Provider.of<solatPoints>(context, listen: false).decreasehealth();
}
break;
}
switch(asar){
case 1:
_AsarEarly?.fire();
break;
case 2:
_AsarLate?.fire();
if (health > 5) {
Provider.of<solatPoints>(context, listen: false).decreasehealth();
}
break;
}
switch(maghrib){
case 1:
_MaghribEarly?.fire();
break;
case 2:
_MaghribLate?.fire();
if (health > 5) {
Provider.of<solatPoints>(context, listen: false).decreasehealth();
}
break;
}
switch(isyak){
case 1:
_IsyakEarly?.fire();
break;
case 2:
_IsyakLate?.fire();
if (health > 5) {
Provider.of<solatPoints>(context, listen: false).decreasehealth();
}
break;
default:
break;
}
}
#override
Widget build(BuildContext context) {
setState(() {
leafcheck();
});
return Scaffold(
backgroundColor: Colors.blueGrey[900],
appBar: AppBar(
backgroundColor: Colors.deepPurple[900],
title: const Text('Bunga Solat'),
),
body: Center(
child: GestureDetector(
child: _riveArtboard == null
? const SizedBox()
: Stack(
children: [
Positioned.fill(
child: Rive(
artboard: _riveArtboard!,
),
),
]
),
),
)
);
}
}
class ClassProfile extends State<ClassProfile> with AutomaticKeepAliveClientMixin {
#override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => false;
#override
Widget build(BuildContext context) {
if(wantKeepAlive) {
super.build(context);
}
.
.
.
.
first set - with AutomaticKeepAliveClientMixin
then, override wantkeepalive variable
at last, defined super.build with if condition in your main widget builder function
In future if you want to persist state of your class then set wantKeepAlive => true

flutter lazyload loading page twice

so im trying to build a lazyload, from my backend i already made per page 5 items. but i dont understand why when i try in flutter the first page is always loaded twice?
for example if i scroll up to page 5, the order of the page will be 1,1,2,3,4 then when i try to refresh, it will show page 5, refresh again then it will show page 1, any idea why?
class ProgressScreen extends StatefulWidget {
#override
_ProgressScreenState createState() => _ProgressScreenState();
}
class _ProgressScreenState extends State<ProgressScreen> {
late MainProgressStore _mainProgressStore;
late UserStore _userStore;
int currentPage = 1;
late int totalPages;
#override
void initState() {
super.initState();
}
#override
void didChangeDependencies() {
super.didChangeDependencies();
// initializing stores
_mainProgressStore = Provider.of<MainProgressStore>(context);
_userStore = Provider.of<UserStore>(context);
if (!_userStore.loading) {
_userStore.getUser();
}
if (!_mainProgressStore.loading) {
_mainProgressStore.postMainProgress(
'loading', 'all', 'desc', 3, 0, currentPage);
}
}
List<Datum> mainProgress = [];
final RefreshController refreshController =
RefreshController(initialRefresh: true);
Future<bool> getmainProgress({bool isRefresh = false}) async {
if (isRefresh) {
currentPage = 1;
} else {
if (currentPage >= totalPages) {
refreshController.loadNoData();
return false;
}
}
final response = await _mainProgressStore.postMainProgress(
'loading', 'all', 'desc', 3, 0, currentPage);
if (_mainProgressStore.success == true) {
final result = _mainProgressStore.mainProgress!.mainProgress;
if (isRefresh) {
mainProgress = result.response;
} else {
mainProgress.addAll(result.response);
}
currentPage++;
totalPages = 10;
print(result.response);
setState(() {});
return true;
} else {
return false;
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppNavBar(),
drawer: DrawerNavBar(userStore: _userStore),
body: _buildMainContent(),
);
}
Widget _buildMainContent() {
return Observer(
builder: (context) {
return _mainProgressStore.success
? _buildRefresh(_mainProgressStore)
: CustomProgressIndicatorWidget();
},
);
}
Widget _buildRefresh(_mainProgressStore) {
return Platform.isIOS
? _buildIOSList(_mainProgressStore)
: _refreshView(_mainProgressStore);
}
Widget _refreshView(_mainProgressStore) {
return SmartRefresher(
controller: refreshController,
enablePullUp: true,
onRefresh: () async {
final result = await getmainProgress(isRefresh: true);
if (result) {
refreshController.refreshCompleted();
} else {
refreshController.refreshFailed();
}
},
onLoading: () async {
final result = await getmainProgress();
if (result) {
refreshController.loadComplete();
} else {
refreshController.loadFailed();
}
},
child: _buildBody(_mainProgressStore));
}
Widget _buildIOSList(_mainProgressStore) {
return Container(
child: CustomScrollView(
slivers: [
CupertinoSliverRefreshControl(
onRefresh: () async {
_mainProgressStore.getHomepage(currentPage);
},
),
SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
return _buildBody(_mainProgressStore);
}, childCount: _mainProgressStore.response.length))
],
),
);
}
Widget _buildBody(_mainProgressStore) {
return SingleChildScrollView(
child: Column(children: <Widget>[
Align(
alignment: Alignment.centerLeft,
child: Container(
padding: EdgeInsets.only(
top: DeviceUtils.getScaledHeight(context, 0.03),
left: DeviceUtils.getScaledWidth(context, 0.06),
bottom: DeviceUtils.getScaledHeight(context, 0.03)),
child: Text(
'MY ORDERS',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: DeviceUtils.getScaledWidth(context, 0.035),
color: Colors.black),
),
),
),
SearchProgress(
currentPage: currentPage, mainProgressStore: _mainProgressStore),
OrderInfo(
progressData: mainProgress, mainProgressStore: _mainProgressStore),
]));
}
}

Flutter weird bug with widget function, sometimes in runs 2 times instead of one

This function have futureBuilder inside and returns another function that returns ListView.
Also I do not want the user to download information from the Internet every time they visit the page, so I put the information downloaded from the Internet into a static variable in class, so i make if else. If this static variable length != 0 , it return me listView instead of make server request with futureBuilder
function that works 2 times instead of one is ListView body
And also this bug created after i added purchases to my application, maybe something wrong there. I don't have any ideas why this happend
this is my complete code
class AddCheckList extends StatefulWidget {
const AddCheckList({Key? key}) : super(key: key);
#override
_AddCheckListState createState() => _AddCheckListState();
}
class _AddCheckListState extends State<AddCheckList> {
String xQueryReqestForCheckListNames = "element CheckListList {for \$a in PACK/OBJECT where (\$a/#inUse = 'True') order by \$a/#name return element CheckList {attribute name {\$a/#name}, attribute sPaid {\$a/#isPaid},attribute oid {\$a/#oid} }}";
String serverLink = "http...";
int addCheckListMethod = 0;
// if addCheckListMethod == 0, then data will download from server and checkLists will be added from server xml data
// if addCheckListMethod == 1, then data will download from assets, and checkLists will be added from assets xml data with getXmlData function
final InAppPurchase _inAppPurchase = InAppPurchase.instance;
final String _productID = '1d7ea644f690ffa';
bool _available = true;
List<ProductDetails> _products = [];
List<PurchaseDetails> _purchases = [];
StreamSubscription<List<PurchaseDetails>>? _subscription;
#override
void initState() {
final Stream<List<PurchaseDetails>> purchaseUpdated = _inAppPurchase.purchaseStream;
_subscription = purchaseUpdated.listen((purchaseDetailsList) {
setState(() {
_purchases.addAll(purchaseDetailsList);
_listenToPurchaseUpdated(purchaseDetailsList);
});
}, onDone: () {
_subscription!.cancel();
}, onError: (error) {
_subscription!.cancel();
});
_initialize();
super.initState();
}
#override
void dispose() {
_subscription!.cancel();
super.dispose();
}
void _initialize() async {
_available = await _inAppPurchase.isAvailable();
List<ProductDetails> products = await _getProducts(
productIds: Set<String>.from(
[_productID],
),
);
setState(() {
_products = products;
});
}
void _listenToPurchaseUpdated(List<PurchaseDetails> purchaseDetailsList) {
purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async {
switch (purchaseDetails.status) {
case PurchaseStatus.pending:
// _showPendingUI();
break;
case PurchaseStatus.purchased:
case PurchaseStatus.restored:
// bool valid = await _verifyPurchase(purchaseDetails);
// if (!valid) {
// _handleInvalidPurchase(purchaseDetails);
// }
break;
case PurchaseStatus.error:
print(purchaseDetails.error!);
// _handleError(purchaseDetails.error!);
break;
default:
break;
}
if (purchaseDetails.pendingCompletePurchase) {
await _inAppPurchase.completePurchase(purchaseDetails);
}
});
}
Future<List<ProductDetails>> _getProducts({required Set<String> productIds}) async {
ProductDetailsResponse response = await _inAppPurchase.queryProductDetails(productIds);
return response.productDetails;
}
void _subscribe({required ProductDetails product}) {
final PurchaseParam purchaseParam = PurchaseParam(productDetails: product);
_inAppPurchase.buyNonConsumable(
purchaseParam: purchaseParam,
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(padding: EdgeInsets.all(14.0), child: listViweBody(addCheckListMethod, serverLink, xQueryReqestForCheckListNames, _products,_subscribe)),
);
}
}
Widget listView(addCheckListMethod, serverLink, product,_subscribe) {
return ListView.separated(
itemCount: CheckListModel.checkListModelNamesFromServer.length,
itemBuilder: (BuildContext context, int index) {
if (CheckListModel.checkListModelNamesFromServer[index].ispaid == false) {
return InkWell(
onTap: () async {
CheckListModel checkList = CheckListModel('', 0, '', 0, 0, 0, '', [], '');
if (addCheckListMethod == 0) {
String xQueryReqestForCheckList = 'for \$a in PACK/OBJECT where \$a/#name="${CheckListModel.checkListModelNamesFromServer[index].name}" return \$a';
var data = await CheckListModel.getDataFromServer(xQueryReqestForCheckList, serverLink);
CheckListModel.addCheckListFromServer(checkList, data);
} else {
CheckListModel.addCheckList(index, checkList);
}
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Добавить описание"),
content: Container(
decoration: BoxDecoration(border: Border.all(color: Color.fromARGB(Desing.colorFromARGBBtn[0], Desing.colorFromARGBBtn[1], Desing.colorFromARGBBtn[2], Desing.colorFromARGBBtn[3]), width: 1), borderRadius: BorderRadius.circular(10)),
child: TextField(
decoration: new InputDecoration.collapsed(hintText: "Описание", border: InputBorder.none),
maxLines: null,
onChanged: (String value) async {
checkList.description = value;
},
),
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("Отменить"),
),
TextButton(
onPressed: () async {
await checkList.writeToFile(checkList.toJson());
CheckListModel.checkLists.add(checkList);
Navigator.pushNamed(context, '/beforeMainCheckList', arguments: {'index': CheckListModel.checkLists.length - 1});
},
child: Text('Добавить'))
],
);
});
},
child: Container(
decoration: BoxDecoration(border: Border.all(color: Color.fromARGB(Desing.colorFromARGBBtn[0], Desing.colorFromARGBBtn[1], Desing.colorFromARGBBtn[2], Desing.colorFromARGBBtn[3]), width: 1), borderRadius: BorderRadius.circular(10)),
width: 50,
height: 80,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"${CheckListModel.checkListModelNamesFromServer[index].name}",
style: TextStyle(fontSize: 30),
)
],
),
),
);
} else {
if (product.length != 0) {
return showPurchaseCheckLists(product, index,_subscribe);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
}
},
separatorBuilder: (BuildContext context, int index) {
return Container(
height: 14,
);
});
}
Widget showPurchaseCheckLists(product, index,_subscribe) {
int getCurrentProduct() {
String? checkListModelid = CheckListModel.checkListModelNamesFromServer[index].checkListId?.toLowerCase();
int indexx = 0;
for (int i = 0; i < product.length; i++) {
if (checkListModelid == product[i].id) {
indexx = i;
}
}
return indexx;
}
return InkWell(
child: Container(
decoration: BoxDecoration(border: Border.all(color: Color.fromARGB(Desing.colorFromARGBBtn[0], Desing.colorFromARGBBtn[1], Desing.colorFromARGBBtn[2], Desing.colorFromARGBBtn[3]), width: 1), borderRadius: BorderRadius.circular(10), color: Color.fromARGB(255, 240, 240, 240)),
width: 50,
height: 80,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"${CheckListModel.checkListModelNamesFromServer[index].name}",
style: TextStyle(fontSize: 25),
),
Text("Купить за ${product[getCurrentProduct()].price}")
],
),
),
onTap: () {
_subscribe(product: product[getCurrentProduct()]);
},
);
}
Widget listViweBody(addCheckListMethod, serverLink, xQueryReqestForCheckListNames, product,_subscribe) {
if (CheckListModel.checkListModelNamesFromServer.length == 0) {
return FutureBuilder(
future: CheckListModel.getDataFromServer(xQueryReqestForCheckListNames, serverLink),
builder: (context, data) {
if (data.connectionState == ConnectionState.done) {
return listView(addCheckListMethod, serverLink, product,_subscribe);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
});
} else {
return listView(addCheckListMethod, serverLink, product,_subscribe);
}
}

AnimatedList is not containing initial data which is loaded using SharedPreferences

I have an AnimatedList whose initial items are getting added before loading data from SharedPreferences. Is there a way, I can load data from device first and then build the screen.
Let's say I'm loading data into myList by for loop using SharedPreferences. And then using the data from myList to create AnimatedList. The problem I'm facing is, the data that was loaded is not Showing in AnimatedList. AnimatedList is getting build before loading the data.
import 'package:material_todo/index.dart';
class TaskScreen extends StatefulWidget {
TaskScreen({this.taskProvider});
final TaskProvider taskProvider;
#override
_TaskScreenState createState() => _TaskScreenState();
}
class _TaskScreenState extends State<TaskScreen>
with SingleTickerProviderStateMixin {
#override
void initState() {
super.initState();
widget.taskProvider.initialiseController(this);
}
String taskRemaining(List tasks) {
var remain = 0;
for (var i in tasks) {
if (i[2] == false) {
remain += 1;
}
}
return '$remain';
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: kWhiteColor,
appBar: widget.taskProvider.editTask
? AppBar(
backgroundColor: Colors.black54,
title: Text('Edit mode'),
centerTitle: false,
leading: IconButton(
onPressed: () {
widget.taskProvider.selectTask(false);
widget.taskProvider.toggleAddTask(false);
widget.taskProvider.toggleEditTask(false);
},
icon: Icon(
Icons.close,
color: Colors.white,
),
),
actions: <Widget>[
IconButton(
onPressed: () {
widget.taskProvider.editingTask();
},
icon: Icon(
Icons.edit,
color: Colors.white,
),
),
IconButton(
onPressed: () {
widget.taskProvider.deleteTask();
widget.taskProvider.toggleEditTask(false);
widget.taskProvider.toggleAddTask(false);
},
icon: Icon(
Icons.delete,
color: Colors.white,
),
),
],
)
: AppBar(
title: Text(
'Tasks',
),
actions: <Widget>[
IconButton(
onPressed: () {
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) =>
// SettingsScreen(provider: taskProvider),
// ),
// );
widget.taskProvider.clearData();
},
icon: Icon(
Icons.settings,
color: Colors.white,
),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
if (widget.taskProvider.showAddTask) {
widget.taskProvider.toggleAddTask(false);
} else {
widget.taskProvider.toggleAddTask(true);
}
try {
widget.taskProvider.selectTask(false);
widget.taskProvider.toggleEditTask(false);
} catch (e) {
print(e);
}
},
child: RotationTransition(
turns: Tween(begin: 0.0, end: 0.125)
.animate(widget.taskProvider.rotationalController),
child: Icon(
Icons.add,
),
),
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
widget.taskProvider.showAddTask
? BuildTaskInput(widget.taskProvider)
: Container(
height: 0,
width: 0,
),
Padding(
padding:
const EdgeInsets.only(left: 30.0, top: 30.0, bottom: 20.0),
child: Text(
taskRemaining(widget.taskProvider.tasks) + ' tasks remaining',
style: TextStyle(
fontSize: 20.0,
color: Colors.grey[800],
fontWeight: FontWeight.w500,
),
),
),
Expanded(
child: AnimatedList(
key: widget.taskProvider.listKey,
initialItemCount: widget.taskProvider.tasks.length,
itemBuilder: (context, index, animation) {
return SizeTransition(
sizeFactor: animation,
child: TaskTile(
title: widget.taskProvider.tasks[index][0],
due: widget.taskProvider.tasks[index][1],
isChecked: widget.taskProvider.tasks[index][2],
isSelected: widget.taskProvider.tasks[index][3],
changeValue: (newValue) {
widget.taskProvider.checkTask(newValue, index);
},
editTask: () {
widget.taskProvider.setTileIndex(index);
widget.taskProvider.selectTask(true);
widget.taskProvider.toggleEditTask(true);
},
),
);
}),
),
],
),
),
);
}
}
import 'package:material_todo/index.dart';
class TaskProvider extends ChangeNotifier {
TaskProvider() {
loadData();
}
//Properties
TextEditingController _textController = TextEditingController();
AnimationController _rotationController;
final GlobalKey<AnimatedListState> _listKey = GlobalKey();
int _tileIndex = 0; //index of selected tile.
bool _showAddTask = false; //whether to show add task container.
bool _editTask = false; // edit task.
bool _deleteCheckTasks = false;
bool _bottomCheckTasks = true;
List<List> _tasks = [
['abc', 'Today', false, false]
]; //stores all the task data.
//Getters
List<List> get tasks => _tasks;
bool get showAddTask => _showAddTask;
bool get editTask => _editTask;
bool get deleteCheckTasks => _deleteCheckTasks;
bool get bottomCheckTasks => _bottomCheckTasks;
int get tileIndex => _tileIndex;
TextEditingController get textController => _textController;
AnimationController get rotationalController => _rotationController;
GlobalKey<AnimatedListState> get listKey => _listKey;
//Setters
void setTileIndex(int index) {
_tileIndex = index;
notifyListeners();
}
void addTask(String title, String due) {
int index = addTaskAtProperIndex(due);
_tasks.insert(index, [
title,
due,
false,
false,
]);
_listKey.currentState.insertItem(index);
notifyListeners();
saveData();
}
void toggleAddTask(bool value) {
_showAddTask = value;
if (!value) {
_rotationController.reverse();
_textController.clear();
} else {
_rotationController.forward();
}
notifyListeners();
print(value);
}
void toggleEditTask(bool value) {
_editTask = value;
notifyListeners();
}
void toggleDeleteTask(bool value) {
_deleteCheckTasks = value;
if (value) {
for (int i = _tasks.length - 1; i >= 0; i--) {
if (_tasks[i][2] == true) {
_tasks.removeAt(i);
}
}
}
notifyListeners();
saveData();
}
void toggleBottomCheckTask(bool value) {
_bottomCheckTasks = value;
if (value) {
for (int i = _tasks.length - 1; i >= 0; i--) {
if (_tasks[i][2] == true) {
_tasks.add(_tasks[i]);
_tasks.removeAt(i);
}
}
}
notifyListeners();
saveData();
}
void checkTask(bool value, int index) {
_tasks[index][2] = value;
if (value && _deleteCheckTasks) {
deleteTask();
}
if (value && _bottomCheckTasks) {
_tasks.add(_tasks[index]);
_tasks.removeAt(index);
}
notifyListeners();
saveData();
}
void selectTask(bool value) {
_tasks[_tileIndex][3] = value;
notifyListeners();
saveData();
}
void deleteTask() {
_tasks.removeAt(_tileIndex);
notifyListeners();
saveData();
}
void replaceTask(String title, String due) {
_tasks.removeAt(_tileIndex);
addTask(title, due);
selectTask(false);
toggleEditTask(false);
notifyListeners();
saveData();
}
void editingTask() {
toggleAddTask(true);
_textController.value = TextEditingValue(text: _tasks[_tileIndex][0]);
}
int addTaskAtProperIndex(String due) {
for (int i = 0; i < _tasks.length; i++) {
if (_tasks[i][1] == due) {
return i;
}
if (due == 'Today') {
return 0;
}
if (due == 'Tomorrow') {
for (int i = _tasks.length - 1; i >= 0; i--) {
if (_tasks[i][1] == 'Today') {
return i + 1;
}
}
return 0;
}
if (due == 'Anytime') {
for (int i = _tasks.length - 1; i >= 0; i--) {
if (_tasks[i][1] == 'Tomorrow') {
return i + 1;
}
}
for (int i = _tasks.length - 1; i >= 0; i--) {
if (_tasks[i][1] == 'Today') {
return i + 1;
}
}
return 0;
}
}
return 0;
}
void initialiseController(TickerProvider ticker) {
_rotationController = AnimationController(
duration: const Duration(milliseconds: 200), vsync: ticker);
}
void saveData() async {
SharedPreferences _prefs = await SharedPreferences.getInstance();
_prefs.setInt('count', _tasks.length);
_prefs.setBool('deleteCheckTasks', _deleteCheckTasks);
_prefs.setBool('bottomCheckTasks', _bottomCheckTasks);
for (int i = 0; i < _tasks.length; i++) {
_prefs.setString('$i 0', _tasks[i][0]);
_prefs.setString('$i 1', _tasks[i][1]);
_prefs.setBool('$i 2', _tasks[i][2]);
}
print('data saved successfully');
}
Future loadData() async {
SharedPreferences _prefs = await SharedPreferences.getInstance();
var _count = _prefs.getInt('count');
if (_count != null) {
for (int i = 0; i < _count; i++) {
var _title = _prefs.getString('$i 0');
var _due = _prefs.getString('$i 1');
var _check = _prefs.getBool('$i 2');
_tasks.add([_title, _due, _check, false]);
}
print('dada loaded successfully');
} else {
print('No data was found');
}
if (_prefs.getBool('deleteCheckTasks') != null) {
_deleteCheckTasks = _prefs.getBool('deleteCheckTasks');
}
if (_prefs.getBool('bottomCheckTasks') != null) {
_bottomCheckTasks = _prefs.getBool('bottomCheckTasks');
}
notifyListeners();
}
Future clearData() async {
SharedPreferences _prefs = await SharedPreferences.getInstance();
_prefs.clear();
}
}