flutter not updating the app on state change - flutter

import 'package:flutter/material.dart';
import 'data.dart';
class Game extends StatefulWidget
{
Game({Key? key}) : super(key: key);
static Data data = Data();
static int counter = 0;
#override
_GameState createState() => _GameState();
}
class _GameState extends State<Game>
{
int counter2 = 0;
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Meh',
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(Game.counter.toString(), ),
Text(counter2.toString(), ),
OutlinedButton(
onPressed: () {
counter2++;
Game.counter++;
print(counter2);
print(Game.counter);
Game.data.save();
setState(() {});
},
child: Text("SAVE"),
),
OutlinedButton(
onPressed: () {
Game.data.load();
setState(() {});
},
child: Text("LOAD"),
),
],
),
),
),
);
}
}
I have to be doing something super stupid but I can't figure out what. You would expect when hitting the save button that the counter variable gets increased and displayed on screen but it's not displaying. Flutter is just ignoring the changes.
Maybe it's something wrong with my emulator? When I switch back to the editor and back to the emulator the value is showing correctly like flutter redrew itself from switching windows but not by clicking the button.
EDIT: This looks like the same issue I'm having, https://github.com/flutter/flutter/issues/17155, any ideas on how to fix it?

I tried your code, and it works for me.
It's definitely an IDE problem.
Try to update Flutter and also your IDE.
To be able to help you, please execute this command
"flutter doctor"
, and send us the result.
Cordially

You can run in https://www.dartpad.dev/, and see youself that the code is working as you expect.

Related

Flutter custom appbar back function is not being triggered

I have a custom AppBar that has a function which should handle the OnBackPressed of the screen, but unfortunately is not being triggered and dunno why.
Basically I want that on pressing the back button, to leave the current screen.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: ComponentAppBar(
showGoBackButton: true,
onGoBackPressed: () => Get.back(),
),
body: Container(),
);
}
The custom app bar file:
import 'package:flutter/material.dart';
class ComponentAppBar extends StatefulWidget implements PreferredSizeWidget {
final bool showGoBackButton;
final Function onGoBackPressed;
const ComponentAppBar({
Key? key,
required this.showGoBackButton,
required this.onGoBackPressed,
}) : super(key: key);
#override
_ComponentAppBarState createState() => _ComponentAppBarState();
#override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
}
class _ComponentAppBarState extends State<ComponentAppBar> {
#override
Widget build(BuildContext context) {
return AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
//
],
),
leading: widget.showGoBackButton
? IconButton(
onPressed: () => widget.onGoBackPressed,
icon: const Icon(
Icons.arrow_back,
color: Colors.black,
),
)
: Container(),
automaticallyImplyLeading: false,
leadingWidth: !widget.showGoBackButton ? 0 : 30,
);
}
}
Pretty straight forward, yet, when pressing the back button nothing happens.
What have I debugged:
Instead of Get.back() use Navigator.pop() - same problem
Add an output onGoBackPressed: () => { print('testing') } - no output
Change onPressed: () => widget.onGoBackPressed to onPressed: () => Get.back(), it works
Change onPressed: () => widget.onGoBackPressed to onPressed: () => { print('test directly in class') }, it works
Also, when using the F5 debug tools, it shows like this, which is very strange:
It's all about callbacks.
You're receiving a callback as argument (onGoBackPressed), and you need to execute it in order for it to work. There are two ways for doing this:
onPressed: widget.onGoBackPressed, //This should work since you're assigning directly onGoBackPressed as the callback to be executed by onPressed
onPressed: ()=>widget.onGoBackPressed.call(), //This should work since you're calling onGoBackPressed callback. In other words, you're executing it. Before, you were just referencing it, without actually executing
Tip: I'd recommend you to avoid dynamics when typing arguments. So, I recommend you to type specifically what your onGoBackPressed callback will return. This way:
final void Function() onGoBackPressed;
Which is the same as
final VoidCallback onGoBackPressed;
Cheers!

How to load different pdf page on initial load

I'm using syncfusion_flutter_pdfviewer package for my flutter project, and I'm trying to pass a specific page number from my Main Page to my Details page. After that it'll load that PDF page number immediacy when the Detail page is open, but I'm stuck, so any help or suggestion would be really appreciated.
I have tried like this, but I'm getting an error on "jumpToPage"
This expression has a type of 'void' so its value can't be used.
Try checking to see if you're using the correct API; there might be a function or call that returns void you didn't expect. Also check type parameters and variables which might also be void.
body: SfPdfViewer.asset(
'data/hymn_pdf/full-songs.pdf',
controller: _pdfViewerController.jumpToPage(widget.number),
),
Full Details page Code.
class DisplayScreen extends StatefulWidget {
final int number;
const DisplayScreen(this.number);
#override
_DisplayScreen createState() => _DisplayScreen();
}
class _DisplayScreen extends State<DisplayScreen> {
final GlobalKey<SfPdfViewerState> _pdfViewerKey = GlobalKey();
late PdfViewerController _pdfViewerController;
#override
void initState() {
_pdfViewerController = PdfViewerController();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Syncfusion Flutter PdfViewer'),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.arrow_drop_down_circle,
color: Colors.white,
),
onPressed: () {
_pdfViewerController.jumpToPage(widget.number); // I got this from synfusion doc and I'm trying to copy it in my controller but I'm getting an error.
},
),
],
),
body: SfPdfViewer.asset(
'data/hymn_pdf/full-songs.pdf',
controller: _pdfViewerController.jumpToPage(widget.number), //I'm getting an error here
),
);
}
}
You cannot just call jumpToPage when assigning the controller. Wrong example:
body: SfPdfViewer.asset(
'data/hymn_pdf/full-songs.pdf',
controller: _pdfViewerController.jumpToPage(widget.number), // <-- nope
),
You need to call the method after the pdf is loaded. For example, call it in the onDocumentLoaded callback function.
Example code:
SfPdfViewer.asset(
'data/hymn_pdf/full-songs.pdf',
controller: _pdfViewerController,
onDocumentLoaded: (details) { // as soon as the doc is loaded
_pdfController.jumpToPage(3); // jump to page 3
},
)

flutter TextField use cause KeyboardListener alway show keyboard on event

using KeyboardListener to gain barcode from scanner, i can't resolve a incredibly stupid problem.
scanning first with keyboardListener work perfectly.
events are gained, barcode too, no virtual keyboard, perfect..
but if i use any Textfield, in the same screen or anywhere in the program, after that,
any event coming to keyboardListener show Virtual Keyboard, without any textfield or else in the screen.
it come to be a nightmare..
I WANT TO AVOID THE KEYBOARD SHOWING, without any input..
don't want to close keyboard, many way on stack overflow to do it.
Step to reproduce:
1:use Physical keyboard or HID to enter serialcode or else whith KeyboardListener
2: Tap on textfield, and write anything and valid text
3: normay, KeyboardListener regain control and get physical events, and the Keyboard show on each...and this is the problem..
youtube video to illustrate (52s)
strange thing. if you use square key to set app background and get foreground, problem disapear.. virtual keyboard dont show again on physical keyboard or HID use... until next textfield use..
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'KbdListener with TextField'),
);
}}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<FocusNode> ListFocusNode = [FocusNode(), FocusNode()];
DateTime whenlastchar = DateTime.now();
List<String> scanned4 = [];
String _receivedtext = "Scanned text here..";
final TextEditingController _myTextControler =
TextEditingController(text: "");
#override
void initState() {
ListFocusNode.first.requestFocus();
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
KeyboardListener(
key: const Key('KeyboardListener-files'),
focusNode: ListFocusNode.first,
autofocus: true,
onKeyEvent: (event) async {
var difference = DateTime.now().difference(whenlastchar);
whenlastchar = DateTime.now();
if (event.character != null) {
if (difference.inMilliseconds > 1000) {
scanned4.clear();
}
scanned4.add(event.character.toString());
if ((event.character == "\n") ||
(event.character == " ") ||
(event.character == 0x09)) {
String tempo =
scanned4.reduce((first, second) => first + second);
scanned4.clear();
tempo = tempo.trim();
// update
setState(() {
_receivedtext = tempo;
});
}
}
},
child: Column(
children: <Widget>[
Text(
_receivedtext,
style: Theme.of(context).textTheme.headlineSmall,
),
],
),
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
TextField(
controller: _myTextControler,
autofocus: false,
focusNode: ListFocusNode.last,
keyboardType: TextInputType.text,
style: const TextStyle(
fontSize: 20,
color: Colors.black,
fontWeight: FontWeight.w400,
),
textInputAction: TextInputAction.done,
onSubmitted: (value) {
print("textfield value: '$value'");
setState(() {
_receivedtext = value;
});
_myTextControler.clear();
FocusScope.of(context)
.requestFocus(ListFocusNode.first);
},
),
Row(children: [
TextButton(
child: const Text("KeyboardListener Focus"),
onPressed: () {
setState(() {
FocusScope.of(context)
.requestFocus(ListFocusNode.first);
});
},
),
]),
],
),
),
],
),
),
);
}
}
ok, so, there is no flutter software solution at this time.
its a google keyboard bug or flutter bug.. or both.
seem that the google keyboard don't dismiss from textfield, TextControler, focusnode or else. or flutter don't destroy callback to google keyboard. don't know.
But, trying other app keyboard, and its magical. its working.. normaly.. fluently.. as expected.
to be honest and complete, perhaps this replacement keyboard don't implement a callback or else.
but he work, the app work, my customers can use it fluently..
without changing any part of my code or flutter code..
the cost? just say to customer. 'install and use this keyboard..'
Did you try using https://pub.dev/packages/flutter_barcode_listener
This Library allows barcode scanning and addresses many problem arising from keyboard listener

W/Choreographer(11277): Frame time is 13.988632 ms in the future! Check that graphics HAL is generating vsync timestamps using the correct timebase

W/Choreographer(11277): Frame time is 13.988632 ms in the future! Check that graphics HAL is generating vsync timestamps using the correct timebase.
This is the error produce at run time.
Flutter is not updating setState content and giving this error,
The code is given below
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'dart:math';
void main() {
runApp(
MaterialApp(
home: Scaffold(
backgroundColor: Colors.redAccent,
appBar: AppBar(
backgroundColor: Colors.red,
title: Center(child: Text('Dicee')),
),
body: MyApp(),
),
),
);
}
class MyApp extends StatefulWidget {
#override
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
int leftDiceNumber = 1;
#override
Widget build(BuildContext context) {
leftDiceNumber = 4;
return Center(
child: Row(
children: <Widget>[
Expanded(
child: FlatButton(
onPressed: () {
setState(() {
leftDiceNumber = (Random().nextInt(6) + 1);
print('images/dice$leftDiceNumber.png');
});
},
child: Image.asset('images/dice$leftDiceNumber.png'),
),
),
Expanded(
child: FlatButton(
onPressed: () {
setState(() {
leftDiceNumber = 5;
});
},
child: Image.asset('images/dice6.png'),
),
),
],
),
);
}
}
please help me out of this
I had the same error. My solution was to open up Device Manager in Android Studio, go to the virtual device and Wipe Data.
In my case, this was a type mismatch error which apparently the logger could not catch.
I was using int in my Model class whereas in firestore the value was in String.
Syncing their types resolved the error!
I had this error when trying to use two Firebase projects in my app. It seems that a lot of the Firebase data is persisted between restarts.
To fix it, I had to comment out my call to Firebase.initializeApp() and run the app once. This seemed to clear out whatever was causing the error.

Why do my variables are successful changed in a StatelessWidget, even tho I get a warning

This is the warning:
This class (or a class which this class inherits from) is marked as '#immutable', but one or more of its instance fields are not final: MyWidget.myVar
The console tells me that the variable must be final. I suspect that I should change my widget to a stateful if I want to change variables, but to me it doesn't makes sense, as the code works as intended. When I change my variable I don't want to change anything on the screen, I just want to use it later.
What I'm doing is wrong? If not, how can I disable this warning?
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: MyWidget(),
),
);
}
class MyWidget extends StatelessWidget {
String myVar;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
MaterialButton(
child: Text('Click me do change variable'),
onPressed: () {
myVar = 'Clicked!';
},
),
MaterialButton(
child: Text('Click me to print the variable'),
onPressed: () {
print(myVar);
},
),
],
),
);
}
}
Your logic is correct and it doesn't really matter since you are not outputting anything on screen. However the best practise is to change it to a Stateful Widget.
It doesn't really affect it in a negative way.
You are getting the warning because all fields in a class extending StatelessWidget should be final.
Fix the warning by adding the final keyword before the type declaration like below:
final String myVar;
From the documentations.
StatelessWidget class. A widget that does not require mutable state.
https://docs.flutter.io/flutter/widgets/StatelessWidget-class.html
I hope this answers your question
The point of changing variable's value in a stateful widget is that you can call
setState(() {
myVar = 'clicked';
});
Which would rebuild the UI, changing a Text widget's content.
Try adding a Text(myVar) to your column, in a stateless widget it wouldn't change on a press of a button. But in a stateful widget it will change.
If you need to change the state of a variable in a Widget, you need to use a StetefullWidget.
class MyWidget extends StatefulWidget {
final String myInitialVar;
const MyWidget({Key key, this.myInitialVar}) : super(key: key);
#override
State<StatefulWidget> createState() => MyWidgetState(myInitialVar);
}
class MyWidgetState extends State<MyWidget> {
String myVar;
MyWidgetState(this.myVar);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
MaterialButton(
child: Text('Click me do change variable'),
onPressed: () {
setState(() {
myVar = 'Clicked!';
});
},
),
MaterialButton(
child: Text('Click me to print the variable'),
onPressed: () {
print(myVar);
},
),
],
),
);
}
}