Mad Sem
Mad Sem
1.INTRODUCTION TO FLUTTER:
In Flutter, widgets are the building blocks of the user interface. They can be
categorized into Stateless Widgets and Stateful Widgets, based on their ability to
maintain state and respond to changes. Understanding the widget lifecycle events
is essential for effective Flutter development.
Stateless Widgets
A Stateless Widget is immutable. It does not hold or manage any state that might
change during its lifecycle. Once created, its appearance and properties remain
fixed until rebuilt.
Example:
@override
return Center(
);
}
}
Stateful Widgets
A Stateful Widget can maintain state that may change during its lifecycle. They
consist of two classes:
1. createState():
○ Called when the widget is created.
○ Links the widget with its associated state object.
2. initState():
○ Invoked once when the state object is inserted into the widget tree.
○ Used for one-time initialization (e.g., setting up listeners or streams).
3. didChangeDependencies():
○ Called when a dependency of the State object changes (e.g., inherited
widgets).
4. build():
○ Invoked whenever the widget needs to be rendered.
○ Returns the UI representation.
5. setState():
○ Triggers a rebuild to update the UI when the state changes.
6. didUpdateWidget():
○ Called when the parent widget rebuilds and passes new data to the
widget.
7. deactivate():
○ Called when the widget is removed temporarily.
8. dispose():
○ Invoked when the widget is permanently removed from the widget
tree.
○ Used to release resources (e.g., closing streams or disposing
controllers).
Example:
@override
int _counter = 0;
@override
void initState() {
super.initState();
print("Widget Initialized");
void _incrementCounter() {
setState(() {
_counter++;
});
@override
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Count: $_counter'),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('Increment'),
),
],
);
@override
void dispose() {
print("Widget Disposed");
super.dispose();
}
Comparison: Stateless vs. Stateful Widgets
In Flutter, Widget Tree and Element Tree are two essential concepts that describe
how the user interface is constructed and managed. While they are closely related,
they serve different purposes in the UI framework.
Widget Tree
The Widget Tree represents the structure and hierarchy of all the widgets in the
app. It is a blueprint that defines what should appear on the screen.
Key Points:
Example:
dart
Copy code
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Widget Tree Example'),
),
body: Center(
child: Text('Hello, Flutter!'),
),
),
);
}
}
Element Tree
The Element Tree is the runtime representation of the Widget Tree. It acts as a
bridge between the immutable Widget Tree and the mutable Render Tree. Each
widget in the Widget Tree corresponds to an Element in the Element Tree.
Key Points:
Relationship to Widgets:
● Stateless Widgets: A single StatelessElement is created for the
widget.
● Stateful Widgets: A StatefulElement is created and links to a State
object to manage mutable state.
Installing the Flutter SDK is the first step to building cross-platform applications.
Below is a step-by-step guide for setting up Flutter on various operating systems:
1. Prerequisites
● Operating System:
○ Windows, macOS, or Linux
● Disk Space:
○ Around 2 GB for the SDK, plus space for IDEs and dependencies
● Software:
○ Git (required for cloning the Flutter repository)
○ IDE (like Android Studio, Visual Studio Code, or IntelliJ)
2. Installation Steps
For Windows
flutter doctor
cd my_first_app
2. Run the app:
flutter run
Creating a "Hello World" app in Flutter is a great way to get started with the
framework. Follow the steps below to create and run your first Flutter application.
hello_world/
├── android/
├── ios/
├── lib/
├── test/
├── web/
└── pubspec.yaml
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Hello World App',
home: Scaffold(
appBar: AppBar(
title: const Text('Hello World App'),
),
body: const Center(
child: Text(
'Hello, World!',
style: TextStyle(fontSize: 24),
),
),
),
);
}
}
Creating a starter project template in Flutter can save you time when starting new
projects. A well-structured template includes basic configurations, reusable
components, and project organization that suits your development style.
starter_template/
├── lib/
│ ├── main.dart # Entry point
│ ├── home_screen.dart # Main screen of the app
│ ├── utils.dart # Utility functions or constants
│ ├── widgets/ # Reusable widgets folder
├── pubspec.yaml # Dependency file
import 'package:flutter/material.dart';
import 'home_screen.dart';
void main() {
runApp(const MyApp());
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Starter Template',
theme: ThemeData(primarySwatch: Colors.blue),
home: const HomeScreen(),
);
}
}
import 'package:flutter/material.dart';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home Screen'),
),
body: const Center(
child: Text(
'Welcome to the Starter Template!',
style: TextStyle(fontSize: 20),
),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'widgets/custom_button.dart';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home Screen'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'Welcome to the Starter Template!',
style: TextStyle(fontSize: 20),
),
const SizedBox(height: 20),
CustomButton(
text: 'Click Me',
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Button Pressed!')),
);
},
),
],
),
),
);
}
}
flutter:
assets:
- assets/images/
flutter run
What You Get
Feel free to extend this template as you learn more about Flutter!
A Full Widget Tree in Flutter refers to the complete hierarchy of widgets that
make up the entire structure of your app's user interface. Each widget in Flutter is a
building block of the UI, and the full widget tree represents all of them, starting
from the root widget down to the leaf nodes.
The widget tree can be broken down into several layers, each responsible for a
specific part of the app's UI. It follows a hierarchical structure, with parent widgets
containing child widgets. The deeper you go into the tree, the more specific the
functionality and styling of the UI become.
○ If the app has multiple screens, the widget tree may include
navigational widgets like Navigator or Drawer to enable screen
transitions.
4. Widgets in the Body:
○ The body of the app is where you place most of your UI components
like buttons, images, text, and containers. These widgets can be
arranged in various layouts such as:
■ Column (for vertical layouts),
■ Row (for horizontal layouts),
■ Stack (for overlapping widgets),
■ GridView (for grid-based layouts).
5. Interaction and Functionality:
○ The theme of the app (e.g., colors, fonts) is defined using the
ThemeData class, and individual widgets like Text, Container,
Button, etc., can have specific styling applied.
How the Full Widget Tree Works
1. Parent-Child Relationships:
○ When you run a Flutter app, the framework starts at the root widget
(MaterialApp or CupertinoApp) and recursively builds the
widget tree.
○ Each widget is created and rendered according to its configuration,
starting from the top-most widget and going down to the deepest,
nested widget.
3. Rendering Process:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
@override
return MaterialApp(
home: Scaffold(
appBar: AppBar(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
),
ElevatedButton(
onPressed: () {
print('Button Pressed!');
},
),
],
),
),
),
);
}
○ Used for passing data down the widget tree efficiently without
needing to pass data manually at every level.
● Flutter Widgets:
○ Flutter offers many built-in widgets to help you create rich UIs, such
as:
■ Container, Column, Row, Stack, GridView
■ Text, Image, Icon, Button
■ ListView, Form, TextField, Checkbox
Here’s a breakdown of how a simple app's full widget tree might look:
MaterialApp
└── Scaffold
├── AppBar
├── Body (Center)
│ └── Column
│ ├── Text (Welcome message)
│ ├── SizedBox (Space)
│ ├── ElevatedButton (Click Me)
└── BottomNavigationBar
Each of these widgets is part of a larger tree, and they each manage a specific part
of the UI.
A Shallow Widget Tree is a simplified version of the full widget tree, where the
widget hierarchy is kept minimal and only the basic layout structure is defined.
Unlike the full widget tree, which includes all the detailed widgets, styles, and
functionality, a shallow widget tree only focuses on the high-level layout without
diving deep into widget-specific details.
1. Minimal Hierarchy: Only the main components of the app’s layout are
included, with few or no nested widgets.
2. No Detailed Styling or Functionality: The shallow tree does not include
things like custom styles, padding, or interactive functionality.
3. Focus on Layout: The goal of a shallow widget tree is to sketch out the
layout or the basic structure of the app, often for rapid prototyping or testing.
● An app bar.
● A text widget.
● A button widget.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Shallow Widget Tree'),
),
body: Center(
child: Column(
children: const [
Text('Hello!'),
ElevatedButton(onPressed: null, child: Text('Click Me')),
],
),
),
),
);
}
}
MaterialApp
└── Scaffold
├── AppBar
└── Body (Center)
└── Column
├── Text (Hello!)
└── ElevatedButton (Click Me)
Once you're satisfied with the layout or structure of the shallow widget tree, you
can begin adding more complexity:
Summary
Animations add interactivity and visual appeal to your app, providing a better user
experience. Flutter offers several built-in animation widgets to easily animate your
app's UI. Here are a few commonly used animation widgets in Flutter:
1. AnimatedContainer
2. AnimatedCrossFade
3. AnimatedOpacity
4. AnimationController
1. AnimatedContainer
void main() {
runApp(const MyApp());
}
@override
_MyAppState createState() => _MyAppState();
}
void _animate() {
setState(() {
_width = _width == 200 ? 300 : 200;
_height = _height == 200 ? 300 : 200;
_color = _color == Colors.blue ? Colors.red : Colors.blue;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("AnimatedContainer Example")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedContainer(
width: _width,
height: _height,
color: _color,
duration: const Duration(seconds: 1),
curve: Curves.easeInOut,
),
ElevatedButton(
onPressed: _animate,
child: const Text("Animate Container"),
),
],
),
),
),
);
}
}
Explanation:
● When the properties (like width, height, or color) are updated using
setState, the AnimatedContainer animates the transition smoothly.
2. AnimatedCrossFade
void main() {
runApp(const MyApp());
}
@override
_MyAppState createState() => _MyAppState();
}
void _toggle() {
setState(() {
_isFirst = !_isFirst;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("AnimatedCrossFade Example")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedCrossFade(
firstChild: const FlutterLogo(size: 100),
secondChild: const Icon(Icons.star, size: 100),
crossFadeState: _isFirst ? CrossFadeState.showFirst :
CrossFadeState.showSecond,
duration: const Duration(seconds: 1),
),
ElevatedButton(
onPressed: _toggle,
child: const Text("Switch Widgets"),
),
],
),
),
),
);
}
}
Explanation:
3. AnimatedOpacity
● Animating the visibility of a widget (e.g., fading in/out an element like a text
or image).
Example:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
@override
_MyAppState createState() => _MyAppState();
}
void _toggleOpacity() {
setState(() {
_opacity = _opacity == 1.0 ? 0.0 : 1.0;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("AnimatedOpacity Example")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedOpacity(
opacity: _opacity,
duration: const Duration(seconds: 1),
child: const FlutterLogo(size: 100),
),
ElevatedButton(
onPressed: _toggleOpacity,
child: const Text("Toggle Opacity"),
),
],
),
),
),
);
}
}
Explanation:
4. AnimationController
● When you need more control over the animation, such as looping, reversing,
or customizing the animation's duration and curve.
Example:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
@override
_MyAppState createState() => _MyAppState();
}
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
);
_animation = Tween<double>(begin: 0.0, end: 200.0).animate(
CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
);
_controller.repeat(reverse: true); // Loop the animation
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text("AnimationController Example")),
body: Center(
child: AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return Container(
width: _animation.value,
height: _animation.value,
color: Colors.blue,
);
},
),
),
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
}
Explanation:
Conclusion
Flutter provides a variety of animation widgets that make it easy to add interactive
and smooth transitions to your app. Here's a quick summary of the widgets:
● AnimatedContainer: Automatically animates changes to a container's
properties like size and color.
● AnimatedCrossFade: Smoothly switches between two widgets with a
fade transition.
● AnimatedOpacity: Animates the opacity of a widget, creating fade-in or
fade-out effects.
● AnimationController: Provides fine control over animations,
allowing you to animate widget properties with custom duration, curves, and
behavior.
In Flutter, form widgets are used to create and manage user input forms. These
widgets allow you to capture user data, perform validation, and apply custom
styling. Decorators are used to style these form fields, enhancing the user
experience. Let's explore form widgets and decorators in detail.
1. Form Widget
The Form widget in Flutter is used to group multiple form fields together. It helps
manage the state of those fields, perform validation, and save the entered data. A
form can include text fields, checkboxes, switches, etc.
Key Features:
● Validation:
You can validate form fields to ensure the entered data is correct
before submitting the form.
● Saving: After validation, the form data can be saved.
● Resetting: The form can be reset to its initial values.
void main() {
runApp(const MyApp());
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: const Scaffold(body: MyForm()),
);
}
}
@override
_MyFormState createState() => _MyFormState();
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey, // Form key for validation
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextFormField(
decoration: const InputDecoration(labelText: 'Name'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your name';
}
return null;
},
onSaved: (value) => _name = value!,
),
TextFormField(
decoration: const InputDecoration(labelText: 'Email'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your email';
}
if
(!RegExp(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$").hasMatch(va
lue)) {
return 'Please enter a valid email address';
}
return null;
},
onSaved: (value) => _email = value!,
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save(); // Save form data
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Name: $_name, Email: $_email')),
);
}
},
child: const Text('Submit'),
),
),
],
),
),
);
}
}
Explanation:
2. TextFormField Widget
The TextFormField widget is one of the most commonly used input fields in a
form. It is an extension of TextField that integrates with the Form widget,
allowing validation and data saving functionality.
Key Properties:
Explanation:
3. InputDecoration
● labelText: The label displayed inside the form field when it is not focused.
● hintText: A placeholder that is shown when the field is empty.
● icon: An icon placed inside the field.
● border: Defines the appearance of the input field's border.
Example:
TextFormField(
decoration: InputDecoration(
labelText: 'Username',
hintText: 'Enter your username',
icon: Icon(Icons.person),
border: OutlineInputBorder(),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 2.0),
),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your username';
}
return null;
},
)
Explanation:
4. FormField Widget
The FormField widget allows for creating custom form fields that are not
limited to text inputs. It can be used for complex form inputs like checkboxes,
switches, or even custom widgets that need validation.
Example: Using FormField for Checkbox:
FormField<bool>(
initialValue: false,
builder: (FormFieldState<bool> state) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
CheckboxListTile(
title: const Text('Agree to terms and conditions'),
value: state.value,
onChanged: (bool? newValue) {
state.didChange(newValue); // Updates field state
},
),
if (state.hasError)
Text(
state.errorText!,
style: TextStyle(color: Colors.red),
),
],
);
},
validator: (value) {
if (value == null || !value) {
return 'You must agree to the terms';
}
return null;
},
)
Explanation:
Once all form fields have been validated, you can submit the form. You typically
use FormState.validate() to validate the fields and
FormState.save() to save the field data.
Explanation:
● validate(): Checks if all form fields are valid according to their validators.
● save(): Saves the form field values after successful validation.
Conclusion
In Flutter, form widgets like Form, TextFormField, and FormField are used
to handle user input in a structured way. InputDecoration allows you to style
these form fields by adding labels, icons, borders, and other visual enhancements.
These tools help in building dynamic, interactive, and user-friendly forms in your
applications.
By leveraging form widgets and decorators, you can create a seamless user
experience with data validation and custom styling.
Navigator in Flutter
Key Concepts:
Hero Animation
Hero animations are used to create a smooth transition between two screens. The
Hero widget takes an object (like an image or text) and animates it from one
screen to another with a shared animation.
● The widget with the same tag on both screens is connected, and Flutter
animates the transition between them.
● Hero animations are typically used for smooth transitions, such as moving
images, icons, or widgets between different screens.
Example Explanation:
● Suppose you have an image on the first screen, and when you navigate to the
second screen, that image smoothly animates from its position on the first
screen to its position on the second screen. This effect is achieved by
wrapping the image in a Hero widget on both screens with the same tag.
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: FirstScreen()));
@override
return Scaffold(
body: Center(
child: GestureDetector(
onTap: () {
Navigator.push(
context,
},
child: Hero(
tag: 'hero-tag',
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
),
),
);
@override
return Scaffold(
child: Hero(
tag: 'hero-tag',
child: Container(
width: 200,
height: 200,
color: Colors.blue,
),
),
),
);
Key Features:
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: BottomNavBarExample()));
@override
int _selectedIndex = 0;
setState(() {
_selectedIndex = index;
});
@override
return Scaffold(
body: Center(
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedIndex,
onTap: _onItemTapped,
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
label: 'Search',
),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle),
label: 'Profile',
),
],
),
);
BottomAppBar
Key Features:
● Customizable Widgets: You can place custom widgets like buttons, icons,
or any other widget in the BottomAppBar.
● Floating Action Button (FAB): Often paired with a FAB, allowing for
actions like creating a new post or sending a message.
Use Case:
● You might use a BottomAppBar with a FAB for creating posts or taking
actions related to the app, with additional icons or custom elements
alongside the button.
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: BottomAppBarExample()));
@override
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomAppBar(
shape: CircularNotchedRectangle(),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
],
),
),
);
● TabBar:
Displays a horizontal row of tabs that users can click to switch
between views.
● TabBarView: Displays the content associated with each selected tab. Each
tab corresponds to a different view or section of the app.
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: TabBarExample()));
}
Summary
Each of these widgets plays a crucial role in making navigation and transitions in
your app smoother and more user-friendly.
Flutter also has other layout widgets like Expanded, Align, and Padding,
which give more flexibility in creating complex layouts.
Setting Up GestureDetector
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: GestureDetectorExample()));
}
Explanation:
You can also detect more advanced gestures with GestureDetector. For
instance, you can detect drag gestures using onPanUpdate:
GestureDetector(
onPanUpdate: (details) {
print("Dragged! Position: ${details.localPosition}");
},
child: Container(
width: 100,
height: 100,
color: Colors.orange,
child: Center(child: Text('Drag Me', style: TextStyle(color: Colors.white))),
),
)
In this example, when the user drags the container, it prints the position of the drag.
Summary:
What is Firebase?
Firestore is a flexible, scalable NoSQL cloud database from Firebase. It allows you
to store and sync data between users and devices in real-time. It is part of Firebase
and works seamlessly with other Firebase features like Firebase Authentication.
To integrate Firebase and Firestore into your Flutter app, you need to:
In your pubspec.yaml file, add the dependencies for Firebase and Firestore.
dependencies:
flutter:
sdk: flutter
firebase_core: ^2.0.0
cloud_firestore: ^5.0.0
In your main.dart file, you need to initialize Firebase before using any Firebase
services.
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
4. Using Firestore:
Here’s a simple example to add, read, and display data using Firestore.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Firestore Example')),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: TextField(
controller: _controller,
decoration: InputDecoration(
hintText: 'Enter Name',
),
),
),
ElevatedButton(
onPressed: _addData,
child: Text('Add Data'),
),
Expanded(
child: StreamBuilder<List<Map<String, dynamic>>>(
stream: _getData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
return Center(child: Text('No data available.'));
} else {
final data = snapshot.data!;
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(data[index]['name']),
subtitle: Text('Age: ${data[index]['age']}'),
);
},
);
}
},
),
),
],
),
);
}
}
Explanation:
1. Firebase Initialization:
Summary:
This setup allows you to manage backend operations like storing user data and
handling real-time updates in your Flutter app.
To use Firebase services (like Firestore, Authentication, etc.) in your Flutter app,
you need to configure your Firebase project. Below are the steps to configure
Firebase for your Flutter project.
Once your Firebase project is created, you need to connect it to your Flutter app.
The steps will be different depending on whether you are using Android or iOS, so
let's go through each.
For Android:
1. In the Firebase Console, go to the Project Overview page and click the
Android icon to add Firebase to your Android app.
2. Register your app by entering the Android package name (found in
android/app/src/main/AndroidManifest.xml).
3. Download the google-services.json file after registration.
4. Move this google-services.json file into your Flutter project's
android/app directory.
For iOS:
1. In the Firebase Console, go to the Project Overview page and click the iOS
icon to add Firebase to your iOS app.
2. Enter your iOS bundle ID (found in ios/Runner.xcodeproj).
3. Download the GoogleService-Info.plist file.
4. Open your Flutter project in Xcode and drag the
GoogleService-Info.plist into the ios/Runner directory of
your Flutter project.
3. Modify Platform-Specific Code:
For Android:
classpath 'com.google.gms:google-services:4.3.3'
For iOS:
1. Open the ios/Podfile and add this line if it's not already present:
Add the necessary Firebase packages to your pubspec.yaml file. For Firestore
and Firebase core, the dependencies will look like this:
dependencies:
flutter:
sdk: flutter
firebase_core: ^2.0.0
cloud_firestore: ^5.0.0
firebase_auth: ^4.0.0 # If you're using Firebase Authentication
Now that you've added Firebase to your project and installed dependencies,
initialize Firebase in the main.dart file before using any Firebase services.
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Firestore Example")),
body: StreamBuilder<List<Map<String, dynamic>>>(
stream: _getData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
return Center(child: Text('No data available.'));
} else {
final data = snapshot.data!;
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(data[index]['name']),
subtitle: Text('Age: ${data[index]['age']}'),
);
},
);
}
},
),
);
}
}
● Run your Flutter app using flutter run and verify that Firebase services
are working correctly (e.g., Firestore can store and retrieve data, or Firebase
Authentication can sign in users).
● If everything is set up correctly, your app should be able to interact with
Firebase features such as Firestore and Authentication.
Additional Setup:
Conclusion:
This guide should help you get started with Firebase in Flutter! Let me know if you
need further assistance with any specific Firebase features.
Cloud Firestore is a flexible, scalable NoSQL cloud database for storing and
syncing data in real-time. To add Firestore to your Flutter app and implement
security rules, follow these steps:
Before you can add Firestore to your Flutter app, make sure you have created a
Firebase project and connected it to your Flutter app as discussed in the previous
sections.
dependencies:
flutter:
sdk: flutter
firebase_core: ^2.0.0
cloud_firestore: ^5.0.0
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Firestore Example")),
body: Column(
children: [
ElevatedButton(
onPressed: _addData,
child: Text('Add Data'),
),
Expanded(
child: StreamBuilder<List<Map<String, dynamic>>>(
stream: _getData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
return Center(child: Text('No data available.'));
} else {
final data = snapshot.data!;
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(data[index]['name']),
subtitle: Text('Age: ${data[index]['age']}'),
);
},
);
}
},
),
),
],
),
);
}
}
Firestore security rules help you control who can read and write to your Firestore
database.
To ensure only authenticated users can access your Firestore database, you can use
Firebase Authentication.
1. Set Up Firebase Authentication
dependencies:
firebase_auth: ^4.0.0
import 'package:firebase_auth/firebase_auth.dart';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
// Sign up with email and password
Future<User?> signUp(String email, String password) async {
try {
UserCredential userCredential = await
_auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
return userCredential.user;
} catch (e) {
print(e);
return null;
}
}
// Sign out
Future<void> signOut() async {
await _auth.signOut();
}
Update your Firestore rules to ensure that users can only access their data. For
example:
service cloud.firestore {
match /databases/{database}/documents {
// Allow read and write to "users" collection if the user is authenticated
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
}
This rule ensures that users can only access their own document in the users
collection.
By following these steps, you can effectively use Firestore as a database for your
Flutter app while ensuring data security through Firebase authentication and
Firestore security rules.