I wanted to create an app that randomly generates my lucky number when i press floatingActionButton. I wanted to do it within 2 dart files.. let me show you the code in dart.main and first_screen.dart.
dart.main
import 'package:demo/app_screens/first_screen.dart';
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
debugShowCheckedModeBanner: false,
home: MyFlutterApp()
));
class MyFlutterApp extends StatefulWidget {
@override
_MyFlutterAppState createState() => _MyFlutterAppState();
}
class _MyFlutterAppState extends State<MyFlutterApp> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.yellow,
centerTitle: true,
title: Text('My first App',style: TextStyle(color: Colors.black, fontSize: 25.0),),
),
body: FirstScreen(),
floatingActionButton: FloatingActionButton(
onPressed: (){
setState(() {
int thatNum = generateLuckyNumber();
});},
child: Icon(Icons.add),
),
);
}
}
and first_screen.dart in the lib/screens directory
import 'dart:math';
import 'package:flutter/material.dart';
class FirstScreen extends StatefulWidget{
@override
_FirstScreenState createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen> {
@override
Widget build(BuildContext context) {
return Material(color: Colors.lightBlue,
child: Center(
child: Text('My lucky number is ${thatNum}',style: TextStyle(
fontSize: 28,color: Colors.black,backgroundColor:Colors.white)),
),
);
}
}
int generateLuckyNumber() {
var random= Random();
int luckyNumber= random.nextInt(10);
return luckyNumber;
}
I would like to use the varibale thatNum declared in main.dart file in the first_screen.dart file.. How do you do that?
The easiest way to do this, pass the thatNum
in FirstScreen
constructor. Do the required changes given below
class _MyFlutterAppState extends State<MyFlutterApp> {
int thatNum; // <- declare thatNum in the class
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.yellow,
centerTitle: true,
title: Text('My first App',style: TextStyle(color: Colors.black, fontSize: 25.0),),
),
body: FirstScreen(thatNum:thatNum), // <-- pass thatNum in constructor
floatingActionButton: FloatingActionButton(
onPressed: (){
setState(() {
thatNum = generateLuckyNumber(); /* <- generateLuckyNumber and assign to thatNum */
});},
child: Icon(Icons.add),
),
);
}
}
In the FirstScreen
declare thatNum
class FirstScreen extends StatefulWidget{
final thatNum; // <- declare thatNum
FirstScreen({this.thatNum});
@override
_FirstScreenState createState() => _FirstScreenState();
}
In _FirstScreenState
check whether the widget.thatNum
is null or not. If it is null assign Loading text or show thatNum
if not widget.thatNum
is not null.
class _FirstScreenState extends State<FirstScreen> {
@override
Widget build(BuildContext context) {
return Material(color: Colors.lightBlue,
child: Center(
child: Text('My lucky number is ${widget.thatNum??"Loading"}',style: TextStyle(
fontSize: 28,color: Colors.black,backgroundColor:Colors.white)),
),
);
}
}
Note: You can also use state management solution, but the above solution solves the issue easily. Still, you can check state management solution here
You can do this thing in two ways:
body: FirstScreen(thatNum), // in Scaffold of main.dart file.
Use it like:
class FirstScreen extends StatefulWidget{
final thatNum;
FirstScreen(this.thatNum);
@override
_FirstScreenState createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen> {
@override
Widget build(BuildContext context) {
return Material(color: Colors.lightBlue,
child: Center(
child: Text('My lucky number is ${widget.thatNum} ??"Loading"}',style: TextStyle(
fontSize: 28,color: Colors.black,backgroundColor:Colors.white)),
),
);
}
}
Create an InheritedWidget as follows.
class MyInheritedWidget extends InheritedWidget {
const MyInheritedWidget({
Key key,
@required this.thatNum,
@required Widget child,
}) : assert(color != null),
assert(child != null),
super(key: key, child: child);
final thatNum;
static MyInheritedWidget of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
}
@override
bool updateShouldNotify(MyInheritedWidget old) => thatNum!= old.thatNum;
}
Change: body: FirstScreen(),
to: body: MyInheritedWidget(child: FirstScreen(), thatNum:thatNum),
Now all the decendent of MyInheritedWidget will be able to access thatNum by using context like:
class _FirstScreenState extends State<FirstScreen> {
@override
Widget build(BuildContext context) {
final thatNum = MyInheritedWidget.of(context).thatNum;
return Material(color: Colors.lightBlue,
child: Center(
child: Text('My lucky number is $thatNum ??"Loading"}',style: TextStyle(
fontSize: 28,color: Colors.black,backgroundColor:Colors.white)),
),
);
}
}
If you have a child Widget that needs thatNum
and that child widget doesn't need to pass thatNum
to any further widget then thatNum
should be passed in dependency.
If you have a long hierarchy of Widget that need this data then InheritedWidget must be used to avoid passing data in each and every child's constructor.
I hope this helps, in case of any doubt please comment. If this answer helps you then please accept and up-vote it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.