- To create an Flutter application
$ flutter create my_new_application
which will create a folder calledmy_new_application
. - After running device write
flutter run
or in VsCode, go to debug section clickstart without debugging
- .idea = Holds some configuration for android studio.
- .vscode = Holds some configuration for visual studio.
- android = When flutter codes compiles to android native code, it will be injected to that folder
- build = Holds output of flutter application, generated and managed by Flutter SDK
- ios = Some with android but ios
- lib = where we write our dart codes
- test = holds the test codes
- .gitignore = for git configuration
- .metadata = Flutter saves some information in here which it needs to build our application correctly
- .packages = Flutter manages internal dependencies in here
- pubspec.lock = File that is generated by pubspec.yaml file
- pubspec.yaml = Folder where we add 3rd party packages and images, fonts
- Widgets are components, the building blocks of our user interface
- Widget is a special type of object:
import 'package:flutter/material.dart';
void main(){
runApp(MyApp());
}
class MyApp extends StatelessWidget{
Widget build(BuildContext context){
return MaterialApp();
}
}
void main(){}
is special method where dart programming starts
- runApp is a normal function but not written by us written by the Flutter team and it is in
material.dart
- runApp tries to take our widget tree and draw something onto screen that's based on that tree.
- Text => Strings
- Numbers => Integers = 2, 30 Floats/Doubles => 20.99
class Person{
String name;
int age;
Person(String name, int age){
this.name = name;
this.age = age;
}
/// shortcut of the below constructor
Person({this.name, this.age});
}
- Wrap your parameters with curly brackets
{ }
void main(){
runApp(MyApp());
}
void sample(name:'ozan', age:24);
void sample(age:22, name:'other');
class MyApp extends StatelessWidget{
Widget build(BuildContext context){
return MaterialApp();
}
void sample({String name, int age}){
///...
}
}
void main(){
runApp(MyApp());
}
void sample(name:'ozan', age:24);
void sample(age:22, name:'other');
class MyApp extends StatelessWidget{
Widget build(BuildContext context){
return MaterialApp();
}
void sample({String name='test', int age=30}){
///...
}
}
void main(){
runApp(MyApp());
}
void sample(name:'ozan', age:24);
void sample(age:22, name:'other');
class MyApp extends StatelessWidget{
Widget build(BuildContext context){
return MaterialApp();
}
void sample({@required String name, @required int age}){
///...
}
}
- If functions which only have one and exactly one expression, then it can be write as a arrow function
void() => runApp(MyApp());
- It has the job for creating base design structure (make ui looks like an real application)
class MyApp extends StatelessWidget{
Widget build(BuildContext context){
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("My First App'),),
body: Text('This is text'),
);
}
}
- Container() widget belongs to the both sides
- Drawn onto the screen, "What the user sees"
- RaisedButton(), Text(), Card()
- Give your app structure and control how visible widgets are drawn onto the screen
- Row(), Column(), ListView()
- If we want items below each other, then use
Column()
- If we want items next to each other, then use
Row()
class MyApp extends StatelessWidget{
Widget build(BuildContext context){
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("My First App'),),
body: Column(
children: [
Text('The Question'),
RaisedButton(child: Text("Answer 1"), onPressed: null)),
]
)
);
}
}
class MyApp extends StatelessWidget{
void answerQuestion(){
print("answer chosen");
}
Widget build(BuildContext context){
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("My First App'),),
body: Column(
children: [
Text('The Question'),
RaisedButton(child: Text("Answer 1"), onPressed: answerQuestion())),
]
)
);
}
}
- This code will gives an error, using the
onPressed: answerQuestion()
without paranthesis, we are saying the flutter "Hey Flutter, when you runsbuild()
method, onPressed value of RaisedButton is the execution of the answerQuestion() method which is onlyprint()
statement. - However Flutter expects us a function not an print statement, therefore we should pass a pointer of that function, we can do that via removing paranthesis:
RaisedButton(child: Text("Answer 1"), onPressed: answerQuestion))
- We can archieve same result we did before in the
onPressed: answerQuestion
via anonmyous function. Example that above is an named function.
Widget build(BuildContext context){
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("My First App'),),
body: Column(
children: [
Text('The Question'),
RaisedButton(child: Text("Answer 1"), onPressed: () => print("Answer Chosen"))
),
]
)
);
}
- Note: Anonymous function doesn't run immediately, if we wanted this, we would add
()
at the end of the anonymous function:
Widget build(BuildContext context){
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("My First App'),),
body: Column(
children: [
Text('The Question'),
RaisedButton(child: Text("Answer 1"), onPressed: () => print("Answer Chosen")())
),
]
)
);
}
class MyApp extends StatelessWidget{
var questionIndex = 0;
void answerQuestion(){
questionIndex = questionIndex + 1;
print(questionIndex);
}
Widget build(BuildContext context){
var questions = [
'What\'s your favorite color?',
'What\'s your favorite animal?'
];
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("My First App'),),
body: Column(
children: [
Text(questionIndex),
RaisedButton(child: Text("Answer 1"), onPressed: answerQuestion())),
]
)
);
}
}
- In this peace of codes, we expect that when we press the button, our text changes to 'What's your favorite animal?'
- But It doesn't work. Because state of the widget didn't change
- State is data/information used by our App.
class MyApp extends StatefulWidget{
State<StatefulWidget> createState(){
return MyAppState();
}
}
class MyAppState extends State<MyApp>{
var questionIndex = 0;
void answerQuestion(){
setState( () {
questionIndex = questionIndex + 1;
}
);
print(questionIndex);
}
Widget build(BuildContext context){
var questions = [
'What\'s your favorite color?',
'What\'s your favorite animal?'
];
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("My First App'),),
body: Column(
children: [
Text(questionIndex),
RaisedButton(child: Text("Answer 1"), onPressed: answerQuestion())),
]
)
);
}
}
setState()
is a function that forces Flutter to re-render the user interface , not an entire user interface- It calls the
build()
where any state class build()
method re-builds its widget tree- Sometimes it is inefficient to re-build all widgets inside the
build()
method. Flutter has a mechanism for that which only redraws(re-render) necessary widgets.
- To make class as private use
_className
- To make fields as private
var _questionIndex
- To make methods as private
void _methodName()
- Stateless widget's
build()
method runs when data comes from output changes. For example, let's say we give a value in the constructor of stateless widget, when this data is changed thenbuild()
method of stateless widget will be called - Stateful widget's
build()
method runs when
class Question extends StatelessWidget{
final String questionText;
Question(this.questionText);
@override
Widget build(BuildContext context){
return Text(questionText);
}
}
import './Question.dart';
class MyApp extends StatefulWidget{
State<StatefulWidget> createState(){
return MyAppState();
}
}
class MyAppState extends State<MyApp>{
var questionIndex = 0;
void answerQuestion(){
setState( () {
questionIndex = questionIndex + 1;
}
);
print(questionIndex);
}
Widget build(BuildContext context){
var _questionIndex = 0;
var questions = [
'What\'s your favorite color?',
'What\'s your favorite animal?'
];
void _answerQuestion(){
setState( (){
_questionIndex = _questionIndex + 1;
})
}
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("My First App'),),
body: Column(
children: [
Question(questions[questionIndex]),
RaisedButton(child: Text("Answer 1"), onPressed: _answerQuestion)),
]
)
);
}
}
-
In this example, when button pressed, because of outer data change in the
build()
of MyAppState class, stateless widgetQuestion(...)
's build() method will call. -
Besides that,
questionText
property inside the stateless widget could be changes internally (insideQuestion
class itself). However this change doesn't affect the user interface, becausebuild()
method ofQuestion
class doesn't run. Therefore we should do something in such a wayquestionText
propery can't be changed after initiliazied.- To do that we use
final
keyword.
- To do that we use
class Person{
String name;
int age;
Person({this.name = "sample", this.age=30});
// another constructor
Person.veryOdl(this.name){
age=60;
}
}
var p1 = Person.veryOld("john");
enum SomeType{
option1,
option2
}
SomeType.option1
-
Use
final
if a value doesn't change from the point of time when our program runs -
Final can be initialized with value.
-
Final it's a runtime constant value, we use this keyword because at the time we are writing code we don't know that the final value will be.
-
Use
const
, if we know the value at the time we are writing code -
Const, it is a compile time constant
-
const can be used in different ways:
const dummy = ['Hello']; // variable dummy is constant, can't be changed
dummy.add('Jhohn');
dummy = 5 // error
var dummy = const ['Hello'] // now hello list is constant
dummy.add('John'); // given an errr that says unmodifiable list etc..
dummy = 5 // allowed, because only hello list is constant