Reputation: 21111
I have 2 screens in my Flutter app: a list of records and a screen for creating and editing records.
If I pass an object to the second screen that means I am going to edit this and if I pass null it means that I am creating a new item. The editing screen is a Stateful widget and I am not sure how to use this approach https://flutter.io/cookbook/navigation/passing-data/ for my case.
class RecordPage extends StatefulWidget {
final Record recordObject;
RecordPage({Key key, @required this.recordObject}) : super(key: key);
@override
_RecordPageState createState() => new _RecordPageState();
}
class _RecordPageState extends State<RecordPage> {
@override
Widget build(BuildContext context) {
//.....
}
}
How can I access recordObject inside _RecordPageState?
Upvotes: 363
Views: 260646
Reputation: 1885
You can override State
class from initState()
if you need to set initial value to your state variables from the StatefulWidget
class _RecordPageState extends State<RecordPage> {
Record _recordObject;
@override
void initState() {
super.initState();
_recordObject = widget.recordObject;
}
@override
Widget build(BuildContext context) {
//.....
}
}
Upvotes: 0
Reputation: 34
This code will clear your doubt :-
class RecordPage extends StatefulWidget {
final Record recordObject;
RecordPage({Key key, @required this.recordObject}) : super(key: key);
@override
_RecordPageState createState() => new _RecordPageState();
}
class _RecordPageState extends State<RecordPage> {
@override
Widget build(BuildContext context) {
return Text(widget.record)
}
}
Upvotes: 0
Reputation: 594
You don't have to create any new object or variable for this reason in the state class, you need to define just a final and nullable variable for your object in the stateful class.
you can access this variable by widget.
like widget.recordObject
class RecordPage extends StatefulWidget {
final Record? recordObject;
RecordPage({required this.recordObject});
@override
_RecordPageState createState() => new _RecordPageState();
}
class _RecordPageState extends State<RecordPage> {
@override
Widget build(BuildContext context) {
return Text(
widget.recordObject == null? "the object is null" : "the object isn't null",
);
}
}
Upvotes: 9
Reputation: 582
You should use a Pub/Sub mechanism.
I prefer to use Rx in many situations and languages. For Dart/Flutter this is the package: https://pub.dev/packages/rxdart
For example, you can use a BehaviorSubject to emit data from widget A, pass the stream to widget B which listens for changes and applies them inside the setState.
Widget A:
// initialize subject and put it into the Widget B
BehaviorSubject<LiveOutput> subject = BehaviorSubject();
late WidgetB widgetB = WidgetB(deviceOutput: subject);
// when you have to emit new data
subject.add(deviceOutput);
Widget B:
// add stream at class level
class WidgetB extends StatefulWidget {
final ValueStream<LiveOutput> deviceOutput;
const WidgetB({Key? key, required this.deviceOutput}) : super(key: key);
@override
State<WidgetB> createState() => _WidgetBState();
}
// listen for changes
@override
void initState() {
super.initState();
widget.deviceOutput.listen((event) {
print("new live output");
setState(() {
// do whatever you want
});
});
}
Upvotes: 0
Reputation: 1331
In my app, often instead of using stateful widgets, I use mainly ChangeNotifierProvider<T>
in main.dart, some model class
class FooModel extends ChangeNotifier {
var _foo = false;
void changeFooState() {
_foo = true;
notifyListeners();
}
bool getFoo () => _foo;
}
and
var foo = context.read<FooModel>();
# or
var foo = context.watch<FooModel>();
in my stateless widgets. IMO this gives me more precise control over the rebuilding upon runtime state change, compared to stateful widgets.
The recipe can be found in the official docs, the concept is called "lifting state up".
Upvotes: 1
Reputation: 147
example as below:
class nhaphangle extends StatefulWidget {
final String username;
final List<String> dshangle;// = ["1","2"];
const nhaphangle({ Key key, @required this.username,@required this.dshangle }) : super(key: key);
@override
_nhaphangleState createState() => _nhaphangleState();
}
class _nhaphangleState extends State<nhaphangle> {
TextEditingController mspController = TextEditingController();
TextEditingController soluongController = TextEditingController();
final scrollDirection = Axis.vertical;
DateTime Ngaysx = DateTime.now();
ScrollController _scrollController = new ScrollController();
ApiService _apiService;
List<String> titles = [];
@override
void initState() {
super.initState();
_apiService = ApiService();
titles = widget.dshangle; //here var is call and set to
}
Upvotes: 15
Reputation: 41
I have to Navigate back to any one of the screens in the list pages but when I did that my onTap function stops working and navigation stops.
class MyBar extends StatefulWidget {
MyBar({this.pageNumber});
final pageNumber;
static const String id = 'mybar_screen';
@override
_MyBarState createState() => _MyBarState();
}
class _MyBarState extends State<MyBar> {
final List pages = [
NotificationScreen(),
AppointmentScreen(),
RequestBloodScreen(),
ProfileScreen(),
];
@override
Widget build(BuildContext context) {
var _selectedItemIndex = widget.pageNumber;
return Scaffold(
bottomNavigationBar: BottomNavigationBar(
elevation: 0,
backgroundColor: Colors.white,
unselectedItemColor: Colors.grey.shade700,
selectedItemColor: Color(kAppColor),
selectedIconTheme: IconThemeData(color: Color(kAppColor)),
currentIndex: _selectedItemIndex,
type: BottomNavigationBarType.fixed,
onTap: (int index) {
setState(() {
_selectedItemIndex = index;
});
},
Upvotes: 4
Reputation: 17219
You don't need to pass parameters to State using it's constructor. You can easily access these using widget.myField.
class MyRecord extends StatefulWidget {
final String recordName;
const MyRecord(this.recordName);
@override
MyRecordState createState() => MyRecordState();
}
class MyRecordState extends State<MyRecord> {
@override
Widget build(BuildContext context) {
return Text(widget.recordName); // Here you direct access using widget
}
}
Pass your data when you Navigate screen :
Navigator.of(context).push(MaterialPageRoute(builder: (context) => MyRecord("WonderWorld")));
Upvotes: 132
Reputation: 1197
class RecordPage extends StatefulWidget {
final Record recordObject;
RecordPage({Key key, @required this.recordObject}) : super(key: key);
@override
_RecordPageState createState() => new _RecordPageState(recordObject);
}
class _RecordPageState extends State<RecordPage> {
Record recordObject
_RecordPageState(this. recordObject); //constructor
@override
Widget build(BuildContext context) {. //closure has access
//.....
}
}
Upvotes: 53
Reputation: 15799
To use recordObject in _RecordPageState, you have to just write widget.objectname like below
class _RecordPageState extends State<RecordPage> {
@override
Widget build(BuildContext context) {
.....
widget.recordObject
.....
}
}
Upvotes: 522