Create new flutter project
- First check for updates
flutter upgrade
- Then create new project
flutter create intro1
- Import project to Android Studio
Hot reload
- change header text and just refresh app
Application piece by piece
- create new code next to the old one
void main() => runApp(SecondApp());
class SecondApp extends StatelessWidget{
@override
Widget build(BuildContext context) => Text("Hello");
}
- hot reload - not working
- hot restart - working but the code generates an error
Another attempt :
class SecondApp extends StatelessWidget{
@override
Widget build(BuildContext context) =>
MaterialApp(
home: Text("Hello")
);
}
- syntax : explain where to put semicolon
- syntax : explain where to put comma
- hot reload : why sometimes we need to do hot restart to remove error and see new app version.
- syntax: arrow function signature
- syntax: home and named parameters
"Alt+Enter -> Wrap with Center"
class SecondApp extends StatelessWidget{
@override
Widget build(BuildContext context) =>
MaterialApp(
home: Center(child: Text("Hello"))
);
}
- add Scaffold
"Alt+Enter" -> wrap with widget
MaterialApp(
home: Scaffold(
body: Center(
child: Text("Hello"),
),
));
- add AppBar
home: Scaffold(
appBar: AppBar(
title: Text("apka"),
)
- Write a test
testWidgets("our new app", (WidgetTester tester) async {
await tester.pumpWidget(SecondApp());
expect(find.text("Hello"), findsOneWidget);
});
- Extract Bar
- Explain private scope
Widget build(BuildContext context) {
var _appBar = AppBar(
title: Text("apka"),
);
return MaterialApp(
home: Scaffold(
appBar: _appBar,
body: Center(
child: Text("Hello"),
),
));
}
- Extract Body
return MaterialApp(
home: Scaffold(
appBar: _appBar,
body: HomePage(),
));
...
class HomePage extends StatelessWidget{
@override
Widget build(BuildContext context) => Center(
child: Text("Hello Again"),
);
}
- Add constructor parameter
- Why final/immutable is important
class HomePage extends StatelessWidget {
final String text;
const HomePage(this.text) : super();
@override
Widget build(BuildContext context) => Center(
child: Text(text),
);
}
- add second row
- "wrap with column"
@override
Widget build(BuildContext context) => Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(text),
Text("second row"),
],
),
);
- add floating action button
Scaffold(
appBar: _appBar,
body: HomePage("Hello from constructor"),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.mail),
onPressed: (){print("button pressed");},
),
)
- send signal
floatingActionButton: FloatingActionButton(
child: Icon(Icons.mail),
onPressed: () => homePage.sendSignal(),
)
...
class HomePage extends StatelessWidget {
final String text;
const HomePage(this.text) : super();
void sendSignal(){
print("signal from button");
}
- try to add counter
var _counter=0;
void sendSignal(){
print("incrementing $_counter");
_counter++;
}
....
children: <Widget>[
Text(text),
Text("counter : $_counter"),
],
It is not working on UI even if we see on console that value is updated
I/flutter ( 8443): incrementing 0
I/flutter ( 8443): incrementing 1
I/flutter ( 8443): incrementing 2
I/flutter ( 8443): incrementing 3
I/flutter ( 8443): incrementing 4
I/flutter ( 8443): incrementing 5
I/flutter ( 8443): incrementing 6
I/flutter ( 8443): incrementing 7
I/flutter ( 8443): incrementing 8
I/flutter ( 8443): incrementing 9
We can also obserwe a warning that not all fields of StatelessWidget are final. Time to introduce another Flutter widget...
Stateful widget
- HomePage -> ctrl+enter -> convert to stateful widget
- after such refactoring sometimes hot restart is needed
Now we have a another element in our chain of invocation so we need to call method in the state through method in the new stateful widget
class HomePage extends StatefulWidget {
final String text;
final _state=_HomePageState();
HomePage(this.text) : super();
void sendSignal(){
_state.sendSignal();
}
@override
_HomePageState createState() => _HomePageState();
}
But it is still not working...
as an exercise try to pass value through stateful widget to state!!!!
lets try something else
Send signal
- mixin as an interface
- static methods
mixin SignalListener{
void onSignal();
}
class SignalDispatcher{
static List<SignalListener> listeners=[];
static sendSignal(){
listeners.forEach((l) => l.onSignal());
}
static register(SignalListener l){
listeners.add(l);
}
}
////...
floatingActionButton: FloatingActionButton(
child: Icon(Icons.mail),
onPressed: () => SignalDispatcher.sendSignal() ,
),
///...
@override
_HomePageState createState(){
var homePageState = _HomePageState();
SignalDispatcher.register(homePageState);
return homePageState;
}
Simplify the code
floatingActionButton: FloatingActionButton(
child: Icon(Icons.mail),
onPressed: SignalDispatcher.sendSignal ,
)