Debug School

rakesh kumar
rakesh kumar

Posted on

Explain callback and maps in Flutter

Callbacks in Flutter
Maps in Flutter
Combining Callbacks and Maps
Creating and using a map to store and retrieve values
Converting a list of integers to a list of their squares
Quiz Implementation in Flutter using map
How to transform a list of JSON objects into a list of Dart objects using the map method
How to apply filter on list of Dart objects
How to convert each body in the list of Post objects to uppercase using the map

Callbacks in Flutter

Callbacks are functions passed as arguments to other functions or widgets. They are commonly used in Flutter to handle events like button presses, form submissions, or custom widget interactions.

Example: Callbacks in Flutter
In this example, we create a simple button that calls a callback function when pressed.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  // This is the callback function
  void _handleButtonClick() {
    print('Button pressed!');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Flutter Callbacks Example')),
      body: Center(
        child: CustomButton(
          onPressed: _handleButtonClick,
        ),
      ),
    );
  }
}

class CustomButton extends StatelessWidget {
  final VoidCallback onPressed;

  CustomButton({required this.onPressed});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: onPressed,
      child: Text('Press me'),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

In this example:

  1. HomePage has a method _handleButtonClick that prints a message.
  2. CustomButton takes a callback onPressed as an argument.
  3. When the button is pressed, the callback is invoked, and the message is printed

Maps in Flutter

A Map is a collection of key-value pairs, where each key is unique. Maps are often used to store data that can be accessed by a specific key.

Example: Using Maps in Flutter
In this example, we create a simple list of users, where each user is represented as a map.
Creating and using a map to store and retrieve values

void main() {
  Map<String, int> fruitPrices = {
    'Apple': 2,
    'Banana': 1,
    'Orange': 3,
  };

  print('Price of an Apple: \$${fruitPrices['Apple']}');
  print('Price of a Banana: \$${fruitPrices['Banana']}');
  print('Price of an Orange: \$${fruitPrices['Orange']}');
}
Enter fullscreen mode Exit fullscreen mode

Converting a list of integers to a list of their squares

void main() {
  List<int> numbers = [1, 2, 3, 4, 5];
  List<int> squares = numbers.map((number) => number * number).toList();

  print('Original list: $numbers');
  print('Squared list: $squares');
}
Enter fullscreen mode Exit fullscreen mode
void main() {
  List<String> words = ['apple', 'banana', 'cherry'];
  List<String> uppercaseWords = words.map((word) => word.toUpperCase()).toList();

  print('Original list: $words');
  print('Uppercase list: $uppercaseWords');
}
Enter fullscreen mode Exit fullscreen mode

output

Original list: [apple, banana, cherry]
Uppercase list: [APPLE, BANANA, CHERRY]
Enter fullscreen mode Exit fullscreen mode

Transforming a List of Objects
If you have a list of custom objects and want to transform a specific property, you can do so as follows:

class Person {
  String name;
  int age;

  Person(this.name, this.age);
}

void main() {
  List<Person> people = [
    Person('John', 25),
    Person('Jane', 30),
    Person('Doe', 20),
  ];

  List<String> names = people.map((person) => person.name).toList();

  print('Original list: ${people.map((p) => p.name).toList()}');
  print('Names list: $names');
}
Enter fullscreen mode Exit fullscreen mode

output

Original list: [John, Jane, Doe]
Names list: [John, Jane, Doe]
Enter fullscreen mode Exit fullscreen mode

Transforming a List of Maps
Suppose you have a list of maps representing people, and you want to extract their names.

void main() {
  List<Map<String, dynamic>> people = [
    {'name': 'John', 'age': 25},
    {'name': 'Jane', 'age': 30},
    {'name': 'Doe', 'age': 20},
  ];

  List<String> names = people.map((person) => person['name'] as String).toList();

  print('Original list: $people');
  print('Names list: $names');
}

Enter fullscreen mode Exit fullscreen mode
Original list: [{name: John, age: 25}, {name: Jane, age: 30}, {name: Doe, age: 20}]
Names list: [John, Jane, Doe]
Enter fullscreen mode Exit fullscreen mode
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  // List of users where each user is represented as a map
  final List<Map<String, String>> users = [
    {'name': 'Alice', 'email': 'alice@example.com'},
    {'name': 'Bob', 'email': 'bob@example.com'},
    {'name': 'Charlie', 'email': 'charlie@example.com'},
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Flutter Maps Example')),
      body: ListView.builder(
        itemCount: users.length,
        itemBuilder: (context, index) {
          final user = users[index];
          return ListTile(
            title: Text(user['name']!),
            subtitle: Text(user['email']!),
          );
        },
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

In this example:

  1. We have a list of maps, where each map represents a user with name and email keys.
  2. We use a ListView.builder to build a list of ListTile widgets, displaying the user information . Summary Callbacks

Purpose: Handle events and pass functions as arguments.
Use Case: Button presses, form submissions, custom widget interactions.

Example: Passing a function to a custom button widget.
Maps

Purpose: Store key-value pairs.
Use Case: Storing and accessing data by unique keys.
Example: List of users represented as maps with name and email keys.
Combining both concepts can help build dynamic and interactive applications in Flutter. Here’s a more complex example that combines callbacks and maps.

Combining Callbacks and Maps

In this example, we'll have a list of users and a button for each user. When the button is pressed, a callback function will be called, displaying the user's name.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  final List<Map<String, String>> users = [
    {'name': 'Alice', 'email': 'alice@example.com'},
    {'name': 'Bob', 'email': 'bob@example.com'},
    {'name': 'Charlie', 'email': 'charlie@example.com'},
  ];

  void _handleUserButtonPress(String name) {
    print('User: $name');
    // You can show a dialog or snackbar as well to display the user name
    // For example, using a Snackbar:
    // ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('User: $name')));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Flutter Callbacks and Maps Example')),
      body: ListView.builder(
        itemCount: users.length,
        itemBuilder: (context, index) {
          final user = users[index];
          return ListTile(
            title: Text(user['name']!),
            subtitle: Text(user['email']!),
            trailing: ElevatedButton(
              onPressed: () => _handleUserButtonPress(user['name']!),
              child: Text('Show Name'),
            ),
          );
        },
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

In this example:

  1. We have a list of users.
  2. For each user, there's a button that, when pressed, calls the _handleUserButtonPress method.
  3. The user's name is printed when the button is pressed . This demonstrates how callbacks and maps can be effectively used together in Flutter to create dynamic and interactive user interfaces.

Quiz Implementation in Flutter using map

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: QuizScreen(),
    );
  }
}

class QuizScreen extends StatefulWidget {
  @override
  _QuizScreenState createState() => _QuizScreenState();
}

class _QuizScreenState extends State<QuizScreen> {
  int _questionIndex = 0;
  List<String> _questions = [
    'What is a callback in Flutter?',
    'How do widgets use callbacks?',
    'What is a map in Dart?',
    'How can you transform a list using the map method?'
  ];

  void _nextQuestion() {
    setState(() {
      _questionIndex = (_questionIndex + 1) % _questions.length;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Quiz Yourself"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              _questions[_questionIndex],
              style: TextStyle(fontSize: 18),
              textAlign: TextAlign.center,
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _nextQuestion,
              child: Text("Next Question"),
            ),
          ],
        ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

How to transform a list of JSON objects into a list of Dart objects using the map method

  List<Post> _posts = jsonData.map((jsonItem) => Post.fromJson(jsonItem)).toList();
Enter fullscreen mode Exit fullscreen mode
class _PostListScreenState extends State<PostListScreen> {
  List<Post> _posts = [];
  List<Post> _filteredPosts = [];
  bool _loading = true;
  String _filterKeyword = '';

  @override
  void initState() {
    super.initState();
    _fetchPosts();
  }

  Future<void> _fetchPosts() async {
    final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));
    if (response.statusCode == 200) {
      final List<dynamic> jsonData = json.decode(response.body);
      setState(() {
        _posts = jsonData.map((jsonItem) => Post.fromJson(jsonItem)).toList();
        _filteredPosts = _posts; // Initialize the filtered posts list
        _loading = false;
      });
    } else {
      throw Exception('Failed to load posts');
    }
  }
Enter fullscreen mode Exit fullscreen mode

Explanation

Image description

Image description

Image description

[
  {"id": 1, "title": "Hello World", "body": "This is the body of the post"},
  {"id": 2, "title": "Flutter Development", "body": "This is the body of the post"},
  {"id": 3, "title": "Dart Programming", "body": "This is the body of the post"}
]
Enter fullscreen mode Exit fullscreen mode

Here’s how the code works step by step:

jsonData:
It is a list of maps (JSON objects) received from the API.

List<dynamic> jsonData = [
  {"id": 1, "title": "Hello World", "body": "This is the body of the post"},
  {"id": 2, "title": "Flutter Development", "body": "This is the body of the post"},
  {"id": 3, "title": "Dart Programming", "body": "This is the body of the post"}
];
Enter fullscreen mode Exit fullscreen mode

Mapping JSON to Post Objects:
Each jsonItem in jsonData is passed to the Post.fromJson factory constructor, creating a Post object for each JSON object.
dart

Iterable<Post> postIterable = jsonData.map((jsonItem) => Post.fromJson(jsonItem));
Enter fullscreen mode Exit fullscreen mode

Converting to List:
The Iterable is then converted to a List using .toList().

List<Post> postList = postIterable.toList();
Enter fullscreen mode Exit fullscreen mode

Assigning to _posts:
The resulting list of Post objects is assigned to the _posts variable.

_posts = postList;
Enter fullscreen mode Exit fullscreen mode

How to apply filter on list of Dart objects

_filteredPosts = _posts
    .where((post) => post.title.contains("FLUTTER"))
    .toList();
Enter fullscreen mode Exit fullscreen mode
posts.map((post) {
      return Post(id: post.id, title: post.title, body: post.body.toUpperCase());
    }).toList();
Enter fullscreen mode Exit fullscreen mode

Original List (_posts):

[
  Post(id: 1, title: "HELLO WORLD", body: "This is the body of the post"),
  Post(id: 2, title: "FLUTTER DEVELOPMENT", body: "This is the body of the post"),
  Post(id: 3, title: "DART PROGRAMMING", body: "This is the body of the post"),
  Post(id: 4, title: "WELCOME TO FLUTTER", body: "This is the body of the post")
]
Enter fullscreen mode Exit fullscreen mode

Filtered List (_filteredPosts):

[
  Post(id: 2, title: "FLUTTER DEVELOPMENT", body: "This is the body of the post"),
  Post(id: 4, title: "WELCOME TO FLUTTER", body: "This is the body of the post")
]
Enter fullscreen mode Exit fullscreen mode

How to convert each body in the list of Post objects to uppercase using the map

final List<Post> posts = [
    Post(id: 1, title: "HELLO WORLD", body: "This is the body of the post"),
    Post(id: 2, title: "FLUTTER DEVELOPMENT", body: "This is the body of the post"),
    Post(id: 3, title: "DART PROGRAMMING", body: "This is the body of the post"),
    Post(id: 4, title: "WELCOME TO FLUTTER", body: "This is the body of the post"),
  ];

Enter fullscreen mode Exit fullscreen mode

List<Post> updatedPosts = posts.map((post) {
      return Post(id: post.id, title: post.title, body: post.body.toUpperCase());
    }).toList();
Enter fullscreen mode Exit fullscreen mode

Top comments (0)