Flutter

Using Cloud Functions in a Flutter App

Introduction

For complex apps, sometimes you just need a bit of logic that isn’t running on a mobile device. Cloud Code makes this possible.

Cloud Code is easy to use because it’s built on the same Parse JavaScript SDK that powers thousands of apps. The only difference is that this code runs in your Parse Server rather than running on the user’s mobile device.

You can use Cloud Code to offload processing to the Parse servers thus increasing your app’s perceived performance. You can create hooks that run whenever an object is saved or deleted. This is useful if you want to validate or sanitize your data. You can also use Cloud Code to modify related objects or kick off other processes such as sending off a push notification.

When you update your Cloud Code, it becomes available to all mobile environments instantly. You don’t have to wait for a new release of your application. This lets you change app behavior on the fly and add new features faster.

This section explains how to create and deploy Cloud Code, followed by how to call a cloud function in Flutter projects through Back4App.

In this guide, the focus is to demonstrate the use of Cloud Function through Flutter. You can find more in-depth information in Parse Official Cloud Code Documentation.

Prerequisites

To complete this tutorial, you will need:

Goal

Run Parse Cloud Code on Back4App from a Flutter App.

Step 1 - Create a Cloud Code File

  1. Go to your App at Back4App website and click on Dashboard.
  2. Find the Cloud Code and click on Functions & Web Hosting. It looks like this:

    Cloud Code block

  3. Upload or create a new file (you can also edit the current main.js file directly on the browser). Then, click at Deploy as shown here:

    Cloud Code Settings

Your main.js file should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Parse.Cloud.define("hello", async (request) => {
    console.log("Hello from Cloud Code!");
    return "Hello from Cloud Code!";
});

Parse.Cloud.define("sumNumbers", async (request) => {
    return (request.params.number1 + request.params.number2);
});

Parse.Cloud.define("createToDo", async (request) => {
    const title = request.params.title;
    const done = request.params.done;

    const Todo = Parse.Object.extend('ToDo');
    const todo = new Todo();
    todo.set('title', title);
    todo.set('done', done);

    try {
        await todo.save();
        return todo;
      } catch (error) {
        console.log('ToDo create - Error - ' + error.code + ' ' + error.message);
      }
});

Parse.Cloud.define("getListToDo", async (request) => {
    let query = new Parse.Query("ToDo");
    query.descending("done");
    return await query.find();
});

You pass parameters to your Cloud function from your Flutter App and access then within the
request.params object.

Step 2 - Understanding the ParseCloudFunction class

The ParseCloudFunction class defines provides methods for interacting with Parse Cloud Functions.

A Cloud Function can be called with ParseCloudFunction.execute({parameters: params}) that returns a map object or ParseCloudFunction.executeObjectFunction<>({parameters: params}) that returns a ParseObject.

Parameters are optional and a map object is expected.

Step 3 - Call Parse Cloud function

Now that you have deployed the Cloud Functions, we can call the functions using Flutter.

Example 1 - Call a Cloud Function and get the return

1
2
3
4
5
6
    //Executes a cloud function with no parameters that returns a Map object
    final ParseCloudFunction function = ParseCloudFunction('hello');
    final ParseResponse parseResponse = await function.execute();
    if (parseResponse.success && parseResponse.result != null) {
      print(parseResponse.result);
    }

The result displayed in the console will be:

1

Example 2 - Call a Cloud Function with parameters and get the return

1
2
3
4
5
6
7
8
9
10
11
    //Executes a cloud function with parameters that returns a Map object
    final ParseCloudFunction function = ParseCloudFunction('sumNumbers');
    final Map<String, dynamic> params = <String, dynamic>{
      'number1': 10,
      'number2': 20
    };
    final ParseResponse parseResponse =
        await function.execute(parameters: params);
    if (parseResponse.success) {
      print(parseResponse.result);
    }

The result displayed in the console will be:

1
flutter: Hello from Cloud Code!

Example 2 - Call a Cloud Function with parameters and get the return

1
2
3
4
5
6
7
8
9
10
11
    //Executes a cloud function with parameters that returns a Map object
    final ParseCloudFunction function = ParseCloudFunction('sumNumbers');
    final Map<String, dynamic> params = <String, dynamic>{
      'number1': 10,
      'number2': 20
    };
    final ParseResponse parseResponse =
        await function.execute(parameters: params);
    if (parseResponse.success) {
      print(parseResponse.result);
    }

The result displayed in the console will be:

1
flutter: 30

Example 3 - Call a Cloud Function with parameters and get ParseObject on return

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    //Executes a cloud function that returns a ParseObject type
    final ParseCloudFunction function = ParseCloudFunction('createToDo');
    final Map<String, dynamic> params = <String, dynamic>{
      'title': 'Task 1',
      'done': false
    };
    final ParseResponse parseResponse =
        await function.executeObjectFunction<ParseObject>(parameters: params);
    if (parseResponse.success && parseResponse.result != null) {
      if (parseResponse.result['result'] is ParseObject) {
        //Transforms the return into a ParseObject
        final ParseObject parseObject = parseResponse.result['result'];
        print(parseObject.objectId);
      }
    }

The result displayed in the console will be:

1
flutter: {"className":"ToDo","objectId":"H0kHsIr6KT","createdAt":"2021-06-25T00:21:10.023Z","updatedAt":"2021-06-25T00:21:10.023Z","title":"Task 1","done":false}

Example 4 - Call a Cloud Function that returns a list of maps that can be converted to a ParseObject

1
2
3
4
5
6
7
8
9
10
11
    //Executes a cloud function with parameters that returns a Map object    
    final ParseCloudFunction function = ParseCloudFunction('getListToDo');
    final ParseResponse parseResponse = await function.execute();
    if (parseResponse.success) {
      if (parseResponse.result != null) {
        for (final todo in parseResponse.result) {
          //Use fromJson method to convert map in ParseObject 
          print(ParseObject('ToDo').fromJson(todo));
        }
      }
    }

The result displayed in the console will be:

1
2
3
4
flutter: {"className":"ToDo","objectId":"cR3G4RccT1","createdAt":"2021-06-23T03:20:34.933Z","updatedAt":"2021-06-23T03:20:34.933Z","title":"Task 1","done":false}
flutter: {"className":"ToDo","objectId":"6BARcICPKe","createdAt":"2021-06-23T03:20:54.294Z","updatedAt":"2021-06-23T03:20:54.294Z","title":"Task 1","done":false}
flutter: {"className":"ToDo","objectId":"tYZA74l89Q","createdAt":"2021-06-23T03:39:42.049Z","updatedAt":"2021-06-23T03:39:42.049Z","title":"Task 1","done":false}
flutter: {"className":"ToDo","objectId":"ArjM8Q7H8D","createdAt":"2021-06-24T03:33:27.925Z","updatedAt":"2021-06-24T03:33:27.925Z","title":"Task 1","done":false}

Step 5 - Call Cloud Function from Flutter

Let’s now use our example call cloud Function in Flutter App, with a simple interface.

Open your Flutter project, go to the main.dart file, clean up all the code, and replace it with:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final keyApplicationId = 'YOUR_APP_ID_HERE';
  final keyClientKey = 'YOUR_CLIENT_KEY_HERE';

  final keyParseServerUrl = 'https://parseapi.back4app.com';

  await Parse().initialize(keyApplicationId, keyParseServerUrl,
      clientKey: keyClientKey, debug: true);

  runApp(MaterialApp(
    title: 'Flutter - GeoPoint',
    debugShowCheckedModeBanner: false,
    home: HomePage(),
  ));
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {

  void doCallCloudCodeHello() async {
    //Executes a cloud function with no parameters that returns a Map object
    final ParseCloudFunction function = ParseCloudFunction('hello');
    final ParseResponse parseResponse = await function.execute();
    if (parseResponse.success && parseResponse.result != null) {
      print(parseResponse.result);
    }
  }

  void doCallCloudCodeSumNumbers() async {
    //Executes a cloud function with parameters that returns a Map object
    final ParseCloudFunction function = ParseCloudFunction('sumNumbers');
    final Map<String, dynamic> params = <String, dynamic>{
      'number1': 10,
      'number2': 20
    };
    final ParseResponse parseResponse =
        await function.execute(parameters: params);
    if (parseResponse.success) {
      print(parseResponse.result);
    }
  }

  void doCallCloudCodeCreateToDo() async {
    //Executes a cloud function that returns a ParseObject type
    final ParseCloudFunction function = ParseCloudFunction('createToDo');
    final Map<String, dynamic> params = <String, dynamic>{
      'title': 'Task 1',
      'done': false
    };
    final ParseResponse parseResponse =
        await function.executeObjectFunction<ParseObject>(parameters: params);
    if (parseResponse.success && parseResponse.result != null) {
      if (parseResponse.result['result'] is ParseObject) {
        //Transforms the return into a ParseObject
        final ParseObject parseObject = parseResponse.result['result'];
        print(parseObject.toString());
      }
    }
  }

  void doCallCloudCodeGetListTodo() async {
    //Executes a cloud function with parameters that returns a Map object
    final ParseCloudFunction function = ParseCloudFunction('getListToDo');
    final ParseResponse parseResponse = await function.execute();
    if (parseResponse.success) {
      if (parseResponse.result != null) {
        for (final todo in parseResponse.result) {
          //Use fromJson method to convert map in ParseObject
          print(ParseObject('ToDo').fromJson(todo));
        }
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Padding(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Container(
            height: 200,
            child: Image.network(
                'https://blog.back4app.com/wp-content/uploads/2017/11/logo-b4a-1-768x175-1.png'),
          ),
          Center(
            child: const Text('Flutter on Back4app - Call Clode Code',
                style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
          ),
          SizedBox(
            height: 8,
          ),
          Container(
            height: 50,
            child: ElevatedButton(
                onPressed: doCallCloudCodeHello,
                child: Text('Cloud Code - Hello'),
                style: ElevatedButton.styleFrom(primary: Colors.blue)),
          ),
          SizedBox(
            height: 8,
          ),
          Container(
            height: 50,
            child: ElevatedButton(
                onPressed: doCallCloudCodeSumNumbers,
                child: Text('Cloud Code - sumNumber'),
                style: ElevatedButton.styleFrom(primary: Colors.blue)),
          ),
          SizedBox(
            height: 8,
          ),
          Container(
            height: 50,
            child: ElevatedButton(
                onPressed: doCallCloudCodeCreateToDo,
                child: Text('Cloud Code - createToDo'),
                style: ElevatedButton.styleFrom(primary: Colors.blue)),
          ),
          SizedBox(
            height: 8,
          ),
          Container(
            height: 50,
            child: ElevatedButton(
                onPressed: doCallCloudCodeGetListTodo,
                child: Text('Cloud Code - getListToDo'),
                style: ElevatedButton.styleFrom(primary: Colors.blue)),
          ),
        ],
      ),
    ));
  }
}

Find your Application Id and Client Key credentials navigating to your app Dashboard at Back4App Website.

Update your code in main.dart with the values of your project’s ApplicationId and ClientKey in Back4app.

  • keyApplicationId = App Id
  • keyClientKey = Client Key

Run the project, and the app will load as shown in the image.

flutter-back4app-associations

Conclusion

At this stage, you are able to code and call your own Cloud Code in your Flutter App using Parse Server Core features through Back4App!.