How to override State class so I could access StatefulWidget instance? - flutter

So I have 2 classes:
class A extends StatefulWidget {
A({Key? key}) : super(key: key);
#override
State<A> createState() => _AState();
}
class _AState extends State<A> {
#override
Widget build(BuildContext context) {
return Container();
}
void func(){}
}
And I want to override the _AState classes func() method. So I do this like this:
class B extends A{
final item = 10;
#override
State<A> createState() => _BState();
}
class _BState extends _AState{
#override
void func() {
widget.item //can't do this
}
}
I have no problem overriding the func() method, but now I also need to access my new variable item, that is declared in B class. And I know I can't do that because instance widget is provided by State<A> class.
So my question is: How to access the variable item from B class in _BState?

Cast the widget to B object
class _BState extends _AState{
#override
void func() {
// (widget as B).item
}
}

Related

Accessing state in widget and making class immutable

I need to expose a couple of functions of a Stateful Widget. Since these functions depend on the state of the widget, I created a variable to store the state.
However, I am getting a compile time warning:
This class (or a class that this class inherits from) is marked as '#immutable', but one or more of its instance fields aren't final.
My Code:
class ItemWidget extends StatefulWidget {
final Record record;
final Function additem;
final Function removeItem;
var state;
ItemWidget(this.record, this.additem, this.removeItem);
#override
_ItemWidgetState createState() {
return this.state = new _ItemWidgetState();
}
// These are public functions which I need to expose.
bool isValid() => state.validate();
void validate() => state.validate();
}
Is there a better way /correct way of achieving this?
Thanks.
You should write the function on state, and access it via GlobalKey.
import 'package:flutter/material.dart';
class ItemWidget extends StatefulWidget {
final Record record;
final Function additem;
final Function removeItem;
const ItemWidget(
Key? key,
this.record,
this.additem,
this.removeItem,
) : super(key: key);
#override
ItemWidgetState createState() => ItemWidgetState();
}
class ItemWidgetState extends State<ItemWidget> {
bool isValid() {
return true;
}
void validate() {}
#override
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
}
https://api.flutter.dev/flutter/widgets/GlobalKey-class.html

how to call function parent to child which is inside model class?

I have this model class which has a refresh method,
class Model{
...
void refresh(){}
}
I'm calling this method from Parent widget like this,
class Parent extends StatefulWidget {
#override
_Parent State createState() => _Parent State();
}
class _Parent State extends State<Parent >
with SingleTickerProviderStateMixin {
final Model model = Model();
#override
Widget build(BuildContext context) {
return Column(
children:[
Child(model: model),
IconButton(onPressed:model.refresh)
]
);
}
}
this is child widget,
class Child extends StatefulWidget {
final Model model;
const Child({
Key? key,
required this.model,
}) : super(key: key);
#override
_ChildState createState() => _ChildState();
}
class _ChildState extends State<Child>
with SingleTickerProviderStateMixin {}
so what I want is to override that method in here and call that whenever it's called from parent.
In short what I need is a callback from parent to child which need to be inside the Model class. So How can I do this?
ok so I knew I can do it with state management but using another library was not a option and I totally forgot about the change notifier so I implemented like this,
class Model extends ChangeNotifier{
void refresh(){
notifyListeners();
}
}
class Child extends StatefulWidget{
final Model model
Child(this.model);
...
#override
initState(){
model.addListener((){});
}
}
class Parent extends StatelessWidget{
final Model model = Model();
...
Child(model),
SomeWidget(
onTap:(){
model.refresh();
}
),
}

The instance member 'widget' can't be accessed in an initializer

In my project, I pass data from one widget to another using this code:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
TranslatorSignUpStep2(transModel: this._translatorModel),
),
);
Then I retrive it in the other widget by the code below:
class TranslatorSignUpStep2 extends StatefulWidget {
final TranslatorModel transModel;
TranslatorSignUpStep2({this.transModel});
#override
_TranslatorSignUpStep2State createState() => _TranslatorSignUpStep2State();
}
The problem is, in the TranslatorSignUpStep2 class I want to assign the passed-in transModel to another variable so I write this code
class _TranslatorSignUpStep2State extends State<TranslatorSignUpStep2> {
TranslatorModel _translatorModel = widget.transModel;
}
But it seems like the widget can't be used outside the build method so I get error saying
The instance member 'widget' can't be accessed in an initializer.. Anyone know how to get over this ?
you can access widget in initState function like this.
class _TranslatorSignUpStep2State extends State<TranslatorSignUpStep2> {
TranslatorModel _translatorModel ;
#override
void initState() {
_translatorModel = widget.transModel;
}
}
Just add the keyword late while initializing:
class TranslatorSignUpStep2 extends StatefulWidget {
final TranslatorModel transModel;
TranslatorSignUpStep2({this.transModel});
#override
_TranslatorSignUpStep2State createState() => _TranslatorSignUpStep2State();
}
class _TranslatorSignUpStep2State extends State<TranslatorSignUpStep2> {
late TranslatorModel _translatorModel = widget.transModel;
}
try this code :
TranslatorSignUpStep2 :
class TranslatorSignUpStep2 extends StatefulWidget {
final TranslatorModel transModel;
TranslatorSignUpStep2({this.transModel});
#override
_TranslatorSignUpStep2State createState() => _TranslatorSignUpStep2State(this.transModel);
}
TranslatorSignUpStep2 class :
class _TranslatorSignUpStep2State extends State<TranslatorSignUpStep2> {
_TranslatorSignUpStep2State(TranslatorModel _tempModel ){
this._translatorModel =_tempModel;
};
TranslatorModel _translatorModel ;
}
Add static keyword when innitializing
class OrderDetails extends StatefulWidget {
int selectedDays;
OrderDetails({
this.range,)};
#override
_OrderDetailsState createState() => _OrderDetailsState();
}
class _OrderDetailsState extends State<OrderDetails> {
String getRange;
#override
void initState() {
super.initState();
getRange = widget.range;
}

How to call a function in a StatefulWidget from another StatefulWidget?

I am trying to call a function(addGeoPoint) from Map class in another function named onDragEnd of the class SwipeButton both of which is are stateful.
class Map extends StatefulWidget {
//Some Code
_MapState createState() => _MapState();
}
class _MapState extends State<Map> {
//Some Functions
void addGeoPoint() async{
}
File 2
class SwipeButton extends StatefulWidget {
// Some Code
#override
SwipeButtonState createState() => SwipeButtonState();
}
class SwipeButtonState extends State<SwipeButton>
with SingleTickerProviderStateMixin {
// Some functions
void _onDragEnd(DragEndDetails details) {
// I want to call the addGeoPoint() function here
}
}
To do so, I tried creating an instance of the class Map as Map mapScreen = new Map and then access the function using mapScreen.addGeoPoint() but, I achieved no success. Any help to solve this problem would be appreciated.
You can use VoidCallBacks to communicate between Widgets:
Map:
class Map extends StatefulWidget {
//Some Code
_MapState createState() => _MapState();
}
class _MapState extends State<Map> {
//Some Functions
void addGeoPoint() async{
//do things
}
Widget buildSwipeButton() {
...
...
return SwipeButton(
onAddGeoPoint: addGeoPoint,
);
}
SwipeButton:
class SwipeButton extends StatefulWidget {
final VoidCallback onAddGeopoint;
SwipeButton({this.onAddGeoPoint});
// Some Code
#override
SwipeButtonState createState() => SwipeButtonState();
}
class SwipeButtonState extends State<SwipeButton>
with SingleTickerProviderStateMixin {
// Some functions
void _onDragEnd(DragEndDetails details) {
// I want to call the addGeoPoint() function here
widget.onAddGeoPoint();
}
}
You can declare your widget like this
class YourWidget extends StatefulWidget {
final Function callback;
YourWidget({#required this.textButton});
#override
YourWidgetState createState() => YourWidgetState();
}
then you can pass de function like this in your stateful parent
YourWidget(
callback: (){}
)
ant then you can use in YourWidget like this in other widget or other function
widget.callback()

Mount a new state in Flutter

I'm new to Flutter. I have made a stateful widget that has multiple options for states, and I have no clue how to switch between them, or if it's even possible. Basically I have:
class SWidget extends StatefulWidget {
State<StatefulWidget> createState(){
return _State1();
}
}
class _State1 extends State<SWidget> {
...
}
class _State2 extends State<SWidget> {
...
}
I want SWidget to switch from _State1 to _State2
Sorry if I don't understand your question but state is often tied to UI. If you need new state then chances are you're wanting to display something different. In that case, you'd want to distinguish the two states (and their UI components) by placing them in their own stateful widgets. You can then switch between the two widgets in a stateful or stateless widget:
class SWidget extends StatelessWidget {
SWidget(this.condition);
final bool condition;
#override
Widget build(BuildContext context) {
return condition ? Foo() : Bar();
}
}
class Foo extends StatefulWidget {
#override
_FooState createState() => _FooState();
}
class _FooState extends State<Foo> {
var _foo = 'foo';
#override
Widget build(BuildContext context) {
return Text(_foo);
}
}
class Bar extends StatefulWidget {
#override
_BarState createState() => _BarState();
}
class _BarState extends State<Bar> {
var _bar = 'bar';
#override
Widget build(BuildContext context) {
return Text(_bar);
}
}
I don't think I've ever seen anyone actually switch the state object out from underneath a widget. You can though easily change a widget's state by calling setState and toggling between values that way too:
class SWidget extends StatefulWidget {
#override
_SWidgetState createState() => _SWidgetState();
}
class _SWidgetState extends State<SWidget> {
var _value = true;
#override
Widget build(BuildContext context) {
return Switch(
value: _value,
onChanged: (value) => setState(() => _value = value),
);
}
}