What do you mean by function

Just like Mathematics, in Flutter, function is everywhere. As a result, we cannot think Mathematics without function. And the same is true for any Flutter App.

In any Flutter App, we will find function everywhere. Therefore, we need to understand how a function works. Moreover, what do we mean by a function.

In our previous section, we have defined a simple function that has some instructions inside its body. Consequently, when we call the function, those instructions are carried out.

However, in the truest sense, a function represents a relationship between two variables.

One variable is independent, and the other is dependent.

When we write y = f(x), it means y and x are related. The relationship is like this: for every x, there is a unique value of y.

Let us see a simple Dart program where we can display this expression.

void main() {
  
 var printing = printANoun('Json Web');
  printing; // Json Web
  
}

void printANoun(String? noun) {
  print('$noun');
}

We can see that the variable “printing” cannot have more than one value for the variable “noun”.

As we pass different value for the variable “noun”, the value of the dependent variable “printing” will change accordingly.

Now we can take forward this conception in a more meaningful way.

We can pass many variables through a function as inputs and make that function more adaptable.

As a result, our functions in Dart and Flutter take inputs and change the instructions accordingly.

/// second type of functions that take some inputs amd we can use that inputs 
/// inside our functions so that we can make it more adaptable by passing 
/// different values

void main() {
  
 printStatement(noun: 'Girl', adjective: 'Good'); 
  printStatement(noun: 'Book', adjective: 'Interesting'); 
  printStatement(noun: 'John Smith', adjective: 'Brave'); 
  printStatement(noun: 'Athens', adjective: 'Ancient'); 
  
  /** 
  :::: OUTPUT:::: 
   Good Girl
Interesting Book
Brave John Smith
Ancient Athens
   
   */
  
}

void printStatement({String? noun, String? adjective}) {
  print('$adjective $noun');
}

Because we have changed the input variables as “named parameter”, now we can safely use those functions.

As we know that adjective is placed before noun, we can call the adjective before noun.

We could have used a dependent variable like “sentence” and established a relationship between the variables.

var sentence = printStatement(noun: 'Girl', adjective: 'Good'); 

However, in this case, we can increase the number of independent variables.

In Flutter, we use such functions in many cases.

Let us consider the “Mood Swing App” that we have built before.

Watch the code below (in bold). We have called two methods as the VoidCallback.

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';

import '../model/mood.dart';

class AppHomePage extends StatelessWidget {
  const AppHomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final mood = Provider.of<Mood>(context);
    final color = Provider.of<Mood>(context);
    return Scaffold(
      backgroundColor: Colors.white70,
      appBar: AppBar(
        title: const Text('Mood Swing App'),
      ),
      body: Center(
        child: Row(
          children: [
            Expanded(
              child: Padding(
                padding: const EdgeInsets.all(18.0),
                child: GestureDetector(
                  onTap: () {
                    mood.changeMood();
                    color.changeColor();
                  },
                  child: Column(
                    children: [
                      Image.asset('images/face${mood.leftFaceIndex + 1}.jpg'),
                      Container(
                        padding: const EdgeInsets.all(5.0),
                        child: Text(
                          'Mood Changes with Color',
                          style: GoogleFonts.laila(
                            textStyle: Theme.of(context).textTheme.headline6,
                            fontSize: 20,
                            fontWeight: FontWeight.w700,
                            color: color.colors[color.leftIndex],
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
            Expanded(
              child: Padding(
                padding: const EdgeInsets.all(18.0),
                child: GestureDetector(
                  onTap: () {
                    mood.changeMood();
                    color.changeColor();
                  },
                  child: Column(
                    children: [
                      Image.asset('images/face${mood.rightFaceIndex + 1}.jpg'),
                      Container(
                        padding: const EdgeInsets.all(5.0),
                        child: Text(
                          'Mood Changes with Color',
                          style: GoogleFonts.laila(
                            textStyle: Theme.of(context).textTheme.headline6,
                            fontSize: 20,
                            fontWeight: FontWeight.w700,
                            color: color.colors[color.rightIndex],
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

We have declared the two methods in our Model folder.

Just to recapitulate let us take a look at the code snippet.

import 'dart:math';

import 'package:flutter/material.dart';

class Mood with ChangeNotifier {
  int leftFaceIndex = 1;
  int rightFaceIndex = 1;

  List colors = [Colors.red, Colors.green, Colors.purple, Colors.deepOrange];
  int leftIndex = 1;
  int rightIndex = 1;

  void changeMood() {
    leftFaceIndex = Random().nextInt(4);
    rightFaceIndex = Random().nextInt(4);
    notifyListeners();
  }

  void changeColor() {
    leftIndex = Random().nextInt(4);
    rightIndex = Random().nextInt(4);
    notifyListeners();
  }
}

We have also used the Provider package that depends on “context”.

Now, although we can change the following code and take them inside one function block, yet it should not work.

Why?

Because the “context” object is missing.

// it will throw an error as context is missing
void changeMoodAndColor() {
    final mood = Provider.of<Mood>(context, listen: false);
    final color = Provider.of<Mood>(context, listen: false);
    mood.changeMood();
    color.changeColor();
  }

Therefore, we need to pass a “context” object as the required input of the function.

// it will work
void changeMoodAndColor(BuildContext context) {
    final mood = Provider.of<Mood>(context, listen: false);
    final color = Provider.of<Mood>(context, listen: false);
    mood.changeMood();
    color.changeColor();
  }

Let us take a full code snippet now.

We have successfully wrapped the instructions inside one code block. As a result we can reuse this code block where “context” is present.

Watch the bold and highlighted sections. You will feel the difference.

Consequently, using Flutter functions wisely can make our Flutter App more adaptable.

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart';

import '../model/mood.dart';

class AppHomePage extends StatelessWidget {
  const AppHomePage({Key? key}) : super(key: key);

  void changeMoodAndColor(BuildContext context) {
    final mood = Provider.of<Mood>(context, listen: false);
    final color = Provider.of<Mood>(context, listen: false);
    mood.changeMood();
    color.changeColor();
  }

  @override
  Widget build(BuildContext context) {
    final mood = context.watch<Mood>();
    final color = context.watch<Mood>();
    return Scaffold(
      backgroundColor: Colors.white70,
      appBar: AppBar(
        title: const Text('Mood Swing App'),
      ),
      body: Center(
        child: Row(
          children: [
            Expanded(
              child: Padding(
                padding: const EdgeInsets.all(18.0),
                child: GestureDetector(
                  onTap: () {
                    changeMoodAndColor(context);
                  },
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Image.asset('images/face${mood.leftFaceIndex + 1}.jpg'),
                      Container(
                        padding: const EdgeInsets.all(5.0),
                        child: Text(
                          'Mood Changes with Color',
                          style: GoogleFonts.laila(
                            textStyle: Theme.of(context).textTheme.headline6,
                            fontSize: 20,
                            fontWeight: FontWeight.w700,
                            color: color.colors[color.leftIndex],
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
            Expanded(
              child: Padding(
                padding: const EdgeInsets.all(18.0),
                child: GestureDetector(
                  onTap: () {
                    changeMoodAndColor(context);
                  },
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Image.asset('images/face${mood.rightFaceIndex + 1}.jpg'),
                      Container(
                        padding: const EdgeInsets.all(5.0),
                        child: Text(
                          'Mood Changes with Color',
                          style: GoogleFonts.laila(
                            textStyle: Theme.of(context).textTheme.headline6,
                            fontSize: 20,
                            fontWeight: FontWeight.w700,
                            color: color.colors[color.rightIndex],
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Now, our “Mood Swing App” just works as before. However, we have learned how we can give inputs to a function (here context), and make it more adaptable.

If you want to clone the whole project and test it yourself please visit this particular branch of GitHub repository.

In the next section we will learn another type of Dart and Flutter function which return a particular data “Type”.

As we progress, we will see their usages more often.

What Next?

Books at Leanpub

Books in Apress

My books at Amazon

GitHub repository

Technical blog

Twitter

Comments

2 responses to “What do you mean by function”

  1. […] we can say that a callback function is a function passed into another function as an […]

  2. […] we can say that a callback function is a function passed into another function as an […]

Leave a Reply