0% found this document useful (0 votes)
6 views

Unit 4 Flutter-1

This document provides a comprehensive guide on networking in Flutter, covering essential topics such as making network requests, handling responses, error management, and best practices. It also introduces Shared Preferences for storing small amounts of data in Flutter applications, detailing steps for implementation and creating a custom class for easier data management. Additionally, it briefly discusses NoSQL databases, highlighting their advantages and features compared to traditional SQL databases.

Uploaded by

rgpandey2015
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

Unit 4 Flutter-1

This document provides a comprehensive guide on networking in Flutter, covering essential topics such as making network requests, handling responses, error management, and best practices. It also introduces Shared Preferences for storing small amounts of data in Flutter applications, detailing steps for implementation and creating a custom class for easier data management. Additionally, it briefly discusses NoSQL databases, highlighting their advantages and features compared to traditional SQL databases.

Uploaded by

rgpandey2015
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 27

Introduction

In the world of mobile app development, network communication is a critical aspect. As


apps become more dynamic, they need to connect with servers to fetch, send, and update
data. Flutter, a powerful UI toolkit, provides a simple yet robust solution for handling
networking tasks in your mobile apps. Whether you’re fetching data from an API or sending
form data to a server, Flutter makes it seamless.

In this guide, we’ll dive into networking in Flutter, covering everything from setting up your
first network request to handling complex scenarios like error handling and JSON parsing.

Why Networking in Flutter Matters

With the rise of real-time data-driven apps, networking is essential for mobile developers.
Flutter supports HTTP networking, enabling developers to build applications that interact
with APIs, databases, and other web services. Whether you’re developing a social media
app, a weather app, or an e-commerce platform, networking is the backbone of these apps’
functionality.

In Flutter, networking is made easier through libraries http, which provide a simple API for
performing HTTP requests and handling responses. Let's explore how you can start with
networking in Flutter.

Fetching Data from the Internet

Fetching Data from the Internet

To fetch data from a web server in Flutter, you can use the http package. This package
simplifies the process of making network requests and handling responses. Below is a basic
example of how to use it:

1. Add the Dependency


First, add the http package to your pubspec.yaml file:
dependencies:
http: ^0.13.3

2. Making the Request


After importing the package, you can send a GET request:

Future<http.Response> createPost(String title, String body) {


return http.post(
Uri.parse('https://jsonplaceholder.typicode.com/posts'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'title': title,
'body': body,
}),
);
}

This example sends a GET request to a server, waits for the response, and decodes the JSON
data. If the request fails, an exception is thrown.

Tip: Always check the status code of the response to handle potential errors.

Explore more Flutter networking strategies on Blup!

Sending Data to the Server

Sending Data to the Server


Networking isn’t just about fetching data. Often, you need to send data from the client to
the server — whether it’s user-generated content, form submissions, or updating records.
Sending POST requests in Flutter follows a similar pattern to GET requests.

Here’s an example of how to send data:

Future<http.Response> createPost(String title, String body) {


return http.post(
Uri.parse('https://jsonplaceholder.typicode.com/posts'),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{
'title': title,
'body': body,
}),
);
}

In this code, we send a POST request with the necessary headers and body.
The jsonEncode function ensures that the data is properly formatted before sending it.

Tip: Be mindful of encoding data to JSON and setting the correct headers for the request.

Handling Different Response Types

When working with APIs, responses can come in various formats — JSON, XML, or even raw
HTML. JSON is the most commonly used format for API responses, and Flutter makes it easy
to handle such data.

To convert the JSON response into Dart objects, you can use the dart:convert package, which
provides functions like jsonDecode and jsonEncode. This is particularly useful when dealing
with structured data like lists and maps.

For example, to decode a JSON response:

var jsonResponse = jsonDecode(response.body);

This parses the JSON response string into a Dart object, allowing you to access and
manipulate the data easily.

Tip: Make sure to handle any errors that might occur during parsing, especially when dealing
with large or complex datasets.

Error Handling in Networking

Networking operations often encounter errors due to connectivity issues, server problems,
or invalid requests. It’s crucial to handle these errors gracefully to improve user experience.
In Flutter, you can manage network errors using try-catch blocks or handling error codes
directly from the HTTP response:

try {
final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));
if (response.statusCode == 200) {
// Success
} else {
throw Exception('Failed to load data');
}
} catch (e) {
// Handle error
print('Error: $e');
}

By handling mistakes like this, you can ensure your app doesn’t crash and provide helpful
feedback to users in case of failure.

Learn more about handling errors and optimizing networking in Flutter on Blup.

Error Handling in Networking

Best Practices for Networking in Flutter

Here are some best practices to follow when working with networking in Flutter:

1. Use Asynchronous Programming: Flutter’s Future and async/await features help


prevent your app from freezing while waiting for a network request.
2. Handle Errors Gracefully: Always account for the possibility of network failures,
timeouts, or server errors. Providing user feedback can greatly improve the
experience.

3. Use Efficient Data Formats: JSON is lightweight and easy to parse, making it ideal for
mobile networking.

4. Keep Your UI Responsive: Avoid blocking the UI thread during network requests. Use
Flutter’s built-in widgets FutureBuilder to update the UI asynchronously.

5. Follow RESTful Principles: For server communication, ensure your network calls
adhere to RESTful standards, utilizing proper HTTP methods and status codes.

Shared Preferences in Flutter


Shared Preferences are a way of storing small information inside the application space.
Storing small amounts of data within an application is a common requirement for modern
apps. Whether it's tracking user authentication, saving settings, or preserving user
preferences, maintaining data between sessions is essential. Flutter provides a simple and
efficient solution for this through Shared Preferences. Shared preferences are the key value
that allows you to store and retrieve simple data types across sessions.

In this article, we are going to learn how to implement a custom class to store and access
values stored in shared preferences.

Let's understand the use of shared preferences with an example.

Example Case for Shared Preferences

Suppose you want to keep track of user authentication. You want to store the information
about the user authentication status so that the user does not need to authenticate each
time he opens the app. In this case, we can store authentication information like status,
access token, and refresh token in the shared preferences and use them whenever we need
across the application.

Steps to Implement Shared Preferences in Flutter

In this example, we are going to see how we can store different type of data in the shared
preferences.

Step 1: Create and Setting Up the Project

Create a flutter project with the help of Android Studio or CLI.

flutter create flutter_sharedpref

cd flutter_sharedpref

Using this the flutter project will be created. The structure of the project is given below

Step 2: Adding Dependencies

Add the shared_preferences package to your pubspec.yaml file

dependencies:

flutter:

sdk: flutter

shared_preferences: ^2.0.6

after changing pubspec.yaml file, Run flutter pub get to install the dependencies.

Step 3 : Importing the package


in your dart file, import the following package to access its functionality

import 'package:shared_preferences/shared_preferences.dart';

Step 4: Saving Data

Let's save different types of data like int, double, String, Boolean, and list.

i). Saving Int Data in Shared Preferences

Future<void> addIntToPref() async {

SharedPreferences prefs = await SharedPreferences.getInstance();

prefs.setInt('intValue', 18);

ii). Saving Double Data in Shared Preferences

Future<void> addDoubleToPref() async {

SharedPreferences prefs = await SharedPreferences.getInstance();

prefs.setDouble('doubleValue', 3.14159265359);

iii). Saving String Data in Shared Preferences

Future<void> addStringToPref() async {

SharedPreferences prefs = await SharedPreferences.getInstance();

prefs.setString('stringValue', 'Hello, World!');

iv). Saving Boolean Data in Shared Preferences

Future<void> addBoolToPref() async {

SharedPreferences prefs = await SharedPreferences.getInstance();

prefs.setBool('boolValue', true);

v). Saving List Data in Shared Preferences

Future<void> addStringListToPref() async {


SharedPreferences prefs = await SharedPreferences.getInstance();

prefs.setStringList('stringListValue', ['Hello', 'World']);

Step 5 : Reading Data

Reading data in share preferences is as easy as storing. we need key to pass to shared
preferences to get the value of data stored.

i). Reading Int Data From Shared Preferences

Future<void> addIntToPref() async {

SharedPreferences prefs = await SharedPreferences.getInstance();

prefs.setInt('intValue', 18);

ii). Reading Double Data From Shared Preferences

Future<double> readDoubleFromPref() async {

SharedPreferences prefs = await SharedPreferences.getInstance();

double doubleValue = prefs.getDouble('doubleValue') ?? 0.0;

return doubleValue;

iii). Saving String Data in Shared Preferences

Future<String> readStringFromPref() async {

SharedPreferences prefs = await SharedPreferences.getInstance();

String stringValue = prefs.getString('stringValue') ?? '';

return stringValue;

iv). Reading Boolean Data From Shared Preferences

Future<bool> readBooleanFromPref() async {

SharedPreferences prefs = await SharedPreferences.getInstance();

bool boolValue = prefs.getBool('isDataSaved') ?? false;

return boolValue;
}

v). Reading List From Shared Preferences

Future<bool> readListFromPref() async {

SharedPreferences prefs = await SharedPreferences.getInstance();

List<String> listData = prefs.getStringList('stringListValue') ?? [];

return listData.isNotEmpty;

Note : As you can notice we have used null-aware operator. this will ensure that when the
value from shared preferences is empty, the value on the right hand side of this operator
gets assigned to variable.

Syntax

variable = expression1 ?? expression2;

variable => Is the variable that will be assigned the value.

expression1 => Is the first expression, which is checked for null.

expression2 => Is the second expression, which is the default value to be used if expression1
is null.

Creating Custom Shared Preferences Class

Now we have basic idea of how to implement shared preferences in flutter, Let's see how
can we make a custom class of shared preferences.

Step 1 : Creating a class

Create a class and name it as per your need. in this case SharedPreferencesManager.

class SharedPreferencesManager {}

Step 2 : Declaring Keys for Shared Preferences

In this step all you need to do is brainstorm your application idea and get the requirements
for which data or values need to store in the shared preferences. accordingly you need to
declare the keys, for example. In authentications scenario we might need to store user-id,
access token, etc. so the keys would be the "user_id", "access_token" .

final String intKey = "intValue";


final String doubleKey = "doubleValue";

final String stringKey = "stringValue";

final String boolKey = "boolValue";

final String listKey = "stringListValue";

Step 3 : Declare All the Required Methods

Declaring the methods which will help store the shared preferences and retrieve them when
method is called, All the methods which

/// Methods for writing data from shared preferences

Future<void> addIntToPref(intData) async {

SharedPreferences prefs = await SharedPreferences.getInstance();

prefs.setInt(intKey, intData);

Future<void> addDoubleToPref(doubleData) async {

SharedPreferences prefs = await SharedPreferences.getInstance();

prefs.setDouble(doubleKey, doubleData);

Future<void> addStringToPref(stringData) async {

SharedPreferences prefs = await SharedPreferences.getInstance();

prefs.setString(stringKey, stringData);

Future<void> addBoolToPref(boolData) async {

SharedPreferences prefs = await SharedPreferences.getInstance();

prefs.setBool(boolKey, boolData);

Future<void> addStringListToPref(listData) async {

SharedPreferences prefs = await SharedPreferences.getInstance();


prefs.setStringList(listKey, listData);

/// Methods for reading data from shared preferences

Future<int> readIntFromPref() async {

SharedPreferences prefs = await SharedPreferences.getInstance();

return prefs.getInt(intKey) ?? 0;

Future<double> readDoubleFromPref() async {

SharedPreferences prefs = await SharedPreferences.getInstance();

return prefs.getDouble(doubleKey) ?? 0.0;

Future<String> readStringFromPref() async {

SharedPreferences prefs = await SharedPreferences.getInstance();

return prefs.getString(stringKey) ?? '';

Future<bool> readBoolFromPref() async {

SharedPreferences prefs = await SharedPreferences.getInstance();

return prefs.getBool(boolKey) ?? false;

Future<List<String>> readListFromPref() async {

SharedPreferences prefs = await SharedPreferences.getInstance();

return prefs.getStringList(listKey) ?? [];

as we can see we have declared methods to store shared preferences as well as read shared
preferences. using the object of this class we can easily call the methods to read and write
data.
Step 4 : Storing Data in Shared Preferences using Custom class Object

Next thing we need to do is create an object of "SharedPreferencesManager" class and use it


to perform operations.

// Create an object of SharedPreferencesManager class

SharedPreferencesManager prefManager = SharedPreferencesManager();

// Call the addIntToPref method and pass the integer value

prefManager.addIntToPref(10);

// Call the addDoubleToPref method and pass the double value

prefManager.addDoubleToPref(10.5);

// Call the addStringToPref method and pass the string value

prefManager.addStringToPref('Hello World');

// Call the addBoolToPref method and pass the boolean value

prefManager.addBoolToPref(true);

// Call the addStringListToPref method and pass the list of strings

prefManager.addStringListToPref(['One', 'Two', 'Three']);

Step 5 : Retrieving Data from Shared Preferences Using Custom class Object

Similarly, we will now call the methods to read the data from shared preferences. we are
assigning these values or data to variables hence we can use them later. for this we are
making one method and inside it reading all the data.

bool isDataRead = false;

int intValue = 0;

double doubleValue = 0.0;

String stringValue = '';

bool boolValue = false;

List<String> stringListValue = [];

// Create an object of SharedPreferencesManager class

SharedPreferencesManager prefManager = SharedPreferencesManager();

// Method to read data from shared preferences


void readData() async {

intValue = await prefManager.readIntFromPref();

doubleValue = await prefManager.readDoubleFromPref();

stringValue = await prefManager.readStringFromPref();

boolValue = await prefManager.readBoolFromPref();

stringListValue = await prefManager.readListFromPref();

as we can see , readData() method is used to read data by calling methods declared in
custom class, and assigned values to declared variables.

Here is the whole functional code:

import 'package:flutter/material.dart';

import 'package:flutter_sharedpref/my_home_page.dart';

void main() {

runApp(const MyApp());

class MyApp extends StatelessWidget {

const MyApp({super.key});

@override

Widget build(BuildContext context) {

return MaterialApp(

debugShowCheckedModeBanner: false,

title: 'Shared Preferences',

theme: ThemeData(

primarySwatch: Colors.blue,

),

home: const MyHomePage(),

);
}

NoSQL, or “Not Only SQL,” is a database management system (DBMS) designed to handle
large volumes of unstructured and semi-structured data. Unlike traditional relational databases
that use tables and pre-defined schemas, NoSQL databases provide flexible data models and
support horizontal scalability, making them ideal for modern applications that require real-
time data processing.
In this article, we will explain what NoSQL databases are, their types, key features, advantages,
disadvantages, and use cases. We will also compare NoSQL with SQL databases, discuss when to
use NoSQL, and highlight some of the most popular NoSQL databases used today.

Why Use NoSQL?


Traditional relational databases follow ACID (Atomicity, Consistency, Isolation,
Durability) principles, ensuring strong consistency and structured relationships between data.
However, as applications evolved to handle big data, real-time analytics, and distributed
environments, NoSQL emerged as a solution with:
 Scalability – Can scale horizontally by adding more nodes instead of upgrading a single
machine.
 Flexibility – Supports unstructured or semi-structured data without a rigid schema.
 High Performance – Optimized for fast read/write operations with large datasets.
 Distributed Architecture – Designed for high availability and partition tolerance in
distributed systems.
Key Features of NoSQL Databases
1. Dynamic schema: NoSQL databases do not have a fixed schema and can accommodate
changing data structures without the need for migrations or schema alterations.
2. Horizontal scalability: NoSQL databases are designed to scale out by adding more nodes to
a database cluster, making them well-suited for handling large amounts of data and high
levels of traffic.
3. Document-based: Some NoSQL databases, such as MongoDB, use a document-based data
model, where data is stored in a schema-less semi-structured format, such as JSON or BSON.
4. Key-value-based: Other NoSQL databases, such as Redis, use a key-value data model, where
data is stored as a collection of key-value pairs.
5. Column-based: Some NoSQL databases, such as Cassandra, use a column-based data model,
where data is organized into columns instead of rows.
6. Distributed and high availability: NoSQL databases are often designed to be highly
available and to automatically handle node failures and data replication across multiple nodes
in a database cluster.
7. Flexibility: NoSQL databases allow developers to store and retrieve data in a flexible and
dynamic manner, with support for multiple data types and changing data structures.
8. Performance: NoSQL databases are optimized for high performance and can handle a high
volume of reads and writes, making them suitable for big data and real-time applications.
Advantages of NoSQL
There are many advantages of working with NoSQL databases such as MongoDB and Cassandra.
The main advantages are high scalability and high availability.

1. High scalability: NoSQL databases use sharding for horizontal scaling. Partitioning of data
and placing it on multiple machines in such a way that the order of the data is preserved is
sharding. Vertical scaling means adding more resources to the existing machine whereas
horizontal scaling means adding more machines to handle the data. Vertical scaling is not that
easy to implement but horizontal scaling is easy to implement. Examples of horizontal scaling
databases are MongoDB, Cassandra, etc. NoSQL can handle a huge amount of data because of
scalability, as the data grows NoSQL scalesThe auto itself to handle that data in an efficient
manner.
2. Flexibility: NoSQL databases are designed to handle unstructured or semi-structured data,
which means that they can accommodate dynamic changes to the data model. This makes
NoSQL databases a good fit for applications that need to handle changing data requirements.
3. High availability: The auto, replication feature in NoSQL databases makes it highly available
because in case of any failure data replicates itself to the previous consistent state.
4. Scalability: NoSQL databases are highly scalable, which means that they can handle large
amounts of data and traffic with ease. This makes them a good fit for applications that need to
handle large amounts of data or traffic
5. Performance: NoSQL databases are designed to handle large amounts of data and traffic,
which means that they can offer improved performance compared to traditional relational
databases.
6. Cost-effectiveness: NoSQL databases are often more cost-effective than traditional
relational databases, as they are typically less complex and do not require expensive hardware
or software.
7. Agility: Ideal for agile development.
Disadvantages of NoSQL
1. Lack of standardization: There are many different types of NoSQL databases, each with its
own unique strengths and weaknesses. This lack of standardization can make it difficult to
choose the right database for a specific application
2. Lack of ACID compliance: NoSQL databases are not fully ACID-compliant, which means that
they do not guarantee the consistency, integrity, and durability of data. This can be a
drawback for applications that require strong data consistency guarantees.
3. Narrow focus: NoSQL databases have a very narrow focus as it is mainly designed for
storage but it provides very little functionality. Relational databases are a better choice in the
field of Transaction Management than NoSQL.
4. Open-source: NoSQL is an databaseopen-source database. There is no reliable standard for
NoSQL yet. In other words, two database systems are likely to be unequal.
5. Lack of support for complex queries: NoSQL databases are not designed to handle
complex queries, which means that they are not a good fit for applications that require
complex data analysis or reporting.
6. GUI is not available: GUI mode tools to access the database are not flexibly available in the
market.
7. Backup: Backup is a great weak point for some NoSQL databases like MongoDB. MongoDB
has no approach for the backup of data in a consistent manner.
8. Large document size: Some database systems like MongoDB and CouchDB store data in
JSON format. This means that documents are quite large (BigData, network bandwidth, speed),
and having descriptive key names actually hurts since they increase the document size.
Step 1: Add Dependencies

In your pubspec.yaml file, add the sqflite and path packages under dependencies:

yaml

CopyEdit

dependencies:

flutter:

sdk: flutter

sqflite: ^2.2.5

path: ^1.8.3

Then, run:

bash

CopyEdit

flutter pub get

✅ Step 2: Import Packages

In your Dart file, import the required packages:

dart
CopyEdit

import 'package:sqflite/sqflite.dart';

import 'package:path/path.dart';

✅ Step 3: Initialize & Open Database


Create a function to open and initialize the database:

Future<Database> initializeDB() async {

final dbPath = await getDatabasesPath();

final path = join(dbPath, 'example.db');

return openDatabase(

path,

onCreate: (db, version) async {

await db.execute('''

CREATE TABLE users(

id INTEGER PRIMARY KEY AUTOINCREMENT,

name TEXT,

age INTEGER

''');

},

version: 1,

);

✅ Step 4: CRUD Operations


📌 Insert Data
dart

CopyEdit
Future<void> insertUser(String name, int age) async {

final db = await initializeDB();

await db.insert(

'users',

{'name': name, 'age': age},

conflictAlgorithm: ConflictAlgorithm.replace,

);

📌 Read Data
dart

CopyEdit

Future<List<Map<String, dynamic>>> getUsers() async {

final db = await initializeDB();

return db.query('users');

📌 Update Data
dart

CopyEdit

Future<void> updateUser(int id, String name, int age) async {

final db = await initializeDB();

await db.update(

'users',

{'name': name, 'age': age},

where: 'id = ?',


whereArgs: [id],

);

📌
Delete Data
dart

CopyEdit

Future<void> deleteUser(int id) async {

final db = await initializeDB();

await db.delete(

'users',

where: 'id = ?',

whereArgs: [id],

);

✅ Step 5: Using the Functions

Example of inserting and retrieving users:

dart

CopyEdit

void main() async {

await insertUser('Alice', 25);

await insertUser('Bob', 30);

List<Map<String, dynamic>> users = await getUsers();

print(users);

}
📌 Best Practices:

1. Avoid opening the database multiple times. Open it once and reuse the instance.
2. Use DAOs (Data Access Objects) for better organization.
3. Consider using moor/drift package if you prefer an ORM-like approach.

Want me to show you how to refactor this code for better structure and scalability? 😊

You said:
Real-time database updates using Firebase, Authentication in Flutter
apps using Firebase Auth.

ChatGPT said:

To implement Real-time Database updates and Authentication using Firebase in Flutter,


follow these steps:

✅ Setting Up Firebase

1.

Create a Firebase Project:


Go to Firebase Console and create a new project.

2.
3.

Add Android/iOS App:

4.

1. Follow the steps to register your app (Package name, App nickname, etc.).
2. Download the google-services.json (for Android) or GoogleService-
Info.plist (for iOS) and place them in your project directory:
1. Android: android/app/
2. iOS: ios/Runner/

5.

Add Dependencies (pubspec.yaml):

6.
yaml

CopyEdit

dependencies:

flutter:

sdk: flutter

firebase_core: ^2.16.0

firebase_auth: ^5.11.0

cloud_firestore: ^4.9.0

Run:

bash

CopyEdit

flutter pub get

✅ Initialize Firebase in Your App


Modify your main.dart file:

dart

CopyEdit

import 'package:flutter/material.dart';

import 'package:firebase_core/firebase_core.dart';

void main() async {

WidgetsFlutterBinding.ensureInitialized();

await Firebase.initializeApp();

runApp(MyApp());

class MyApp extends StatelessWidget {

@override
Widget build(BuildContext context) {

return MaterialApp(

title: 'Flutter Firebase App',

theme: ThemeData(primarySwatch: Colors.blue),

home: HomeScreen(),

);

✅ Firebase Authentication (Sign Up & Sign In)


📌 Sign Up User
dart

CopyEdit

import 'package:firebase_auth/firebase_auth.dart';

Future<void> signUp(String email, String password) async {

try {

await FirebaseAuth.instance.createUserWithEmailAndPassword(

email: email,

password: password,

);

} catch (e) {

print(e.toString());

📌 Sign In User
dart

CopyEdit
Future<void> signIn(String email, String password) async {

try {

await FirebaseAuth.instance.signInWithEmailAndPassword(

email: email,

password: password,

);

} catch (e) {

print(e.toString());

📌 Sign Out User


dart

CopyEdit

Future<void> signOut() async {

await FirebaseAuth.instance.signOut();

📌 Get Current User


dart

CopyEdit

User? getCurrentUser() {

return FirebaseAuth.instance.currentUser;

✅ Real-Time Database Updates Using Firestore


📌 Adding Data to Firestore
dart

CopyEdit
import 'package:cloud_firestore/cloud_firestore.dart';

Future<void> addUser(String userId, String name, int age) async {

await FirebaseFirestore.instance.collection('users').doc(userId).set({

'name': name,

'age': age,

'createdAt': FieldValue.serverTimestamp(),

});

📌 Reading Data (Real-Time Listener)


dart

CopyEdit

Stream<List<Map<String, dynamic>>> getUsers() {

return FirebaseFirestore.instance

.collection('users')

.snapshots()

.map((snapshot) => snapshot.docs.map((doc) =>


doc.data()).toList());

📌 Updating Data
dart

CopyEdit

Future<void> updateUser(String userId, String name) async {

await
FirebaseFirestore.instance.collection('users').doc(userId).update({

'name': name,

});

}
📌 Deleting Data
dart

CopyEdit

Future<void> deleteUser(String userId) async {

await FirebaseFirestore.instance.collection('users').doc(userId).delete();

✅ Using Data in Your App (Example UI)


dart

CopyEdit

import 'package:flutter/material.dart';

import 'package:cloud_firestore/cloud_firestore.dart';

class UserListScreen extends StatelessWidget {

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(title: Text("Users")),

body: StreamBuilder<List<Map<String, dynamic>>>(

stream: getUsers(),

builder: (context, snapshot) {

if (snapshot.connectionState == ConnectionState.waiting) {

return Center(child: CircularProgressIndicator());

if (snapshot.hasError) {

return Center(child: Text("Error: ${snapshot.error}"));

}
final users = snapshot.data ?? [];

return ListView.builder(

itemCount: users.length,

itemBuilder: (context, index) {

final user = users[index];

return ListTile(

title: Text(user['name']),

subtitle: Text("Age: ${user['age']}"),

);

},

);

},

),

);

You might also like