构建 Flutter 后端分步指南

Step-by-step guide to build a Flutter backend
Step-by-step guide to build a Flutter backend

本文将讨论 Flutter,这是 Google 开发的一款开源 UI 软件开发工具包。

我们将探讨使用 Flutter 的优缺点,并重点介绍 Flutter 应用程序的不同后台选项。

最后,您将学习如何使用 Back4apps 的后端即服务(BaaS)功能为 Flutter 应用程序构建一个可用的后端。

什么是Flutter?

Flutter 是一个跨平台开发框架,可让您快速构建原生感的 Android、iOS、Web、Linux、macOS 和 Windows 应用程序。

有了 Flutter,您会发现构建特定平台应用程序的许多复杂问题都迎刃而解了。Flutter 还以其快速的性能和漂亮的 UI 部件而闻名。

Flutter 团队自己将这项技术定义为

Google的一个开源框架,用于从单一代码库中构建美观的、本地编译的多平台应用程序。

Flutter 的三大优势和局限

优势局限性
Flutter 是一个快速框架,具有大量即用型功能,可帮助您加快应用程序的开发时间。Flutter 应用程序往往比使用 React Native 等其他框架构建的应用程序更大。
Flutter 应用程序是跨平台的,可在 Android 和 iOS 上运行,为您节省开发时间和资金。Flutter 是一个相对较新的框架,社区规模相对较小。这可能会使您在需要时很难找到帮助和支持。
Flutter 易于学习,即使是初学者也不例外。精彩的文档让你轻松上手。Flutter 使用 Dart 编程语言,这种语言不像 Java 或 JavaScript 等其他语言那样广为人知。这可能会限制您可用的软件包。

后台类型有哪些?

在构建任何应用程序时,选择正确的后台选项来处理服务器端任务都是非常重要的。

每种类型的后端都有自己的强项,您的应用程序的特定需求应指导您选择后端。

下面的小节将重点介绍你可以使用的不同后台选项、它们是什么、如何工作以及它们如何最适合你的应用程序的需要。

IaaS

如果您要处理的是一个拥有众多用户的大型应用程序,那么IaaS是您应该考虑采用的后端选项。IaaS 是一种云计算模式,代表基础设施即服务

云计算是一种由第三方供应商通过互联网提供计算资源(如服务器、存储和应用程序)的模式。

这些资源可按需访问,按需付费。使用 IaaS,云提供商将维护主要的底层计算基础设施,而您则可以完全控制应用程序的数据配置、操作系统和所有其他后端要求。

这使它成为需要增加或减少计算资源的应用程序的良好后端选择。

PaaS

平台即服务(PaaS)和基础设施即服务(IaaS)是两种不同的云计算模式,各有不同的用途。虽然二者都具有灵活性和可扩展性,但它们在开发和部署应用程序方面满足了不同的需求。

PaaS 后端将为您提供完整的开发环境,抽象出管理服务器、网络和存储的复杂性。如果您想专注于构建和维护应用程序,而无需担心基础设施管理,那么 PaaS 将是您的最佳选择。

BaaS

后端即服务(BaaS)后端可为您提供随时可用的后端服务和功能,使他们能够专注于构建和增强应用程序的用户体验,而无需管理后端基础设施。

有了 BaaS,开发人员可以通过应用程序接口访问用户验证、数据库和存储等功能,无需设置和维护后端服务器。

这就像使用一块现成的拼图,完全适合您的应用程序,省时省力。

从本质上讲,BaaS 简化了开发流程,使开发人员能够专注于应用程序面向用户的方面,同时依靠预构建的后端服务来处理繁重的工作。

如何使用后端即服务构建 Flutter 后端

本节将讨论如何开始构建 Flutter 应用程序的后端。Back4app 平台是构建可扩展、安全、灵活且易于部署的后端应用程序的绝佳选择。

Back4app 概览

Back4App 是一个后台即服务(BaaS)平台,通过提供完整的后台基础设施简化移动和网络应用程序开发。

使用 Back4App,您就可以专注于构建应用程序的前端功能。

该平台提供各种随时可用的后端服务,包括数据库、应用程序接口和云功能。

Back4app 的主要功能/优势包括

  • 关系数据库和非关系数据库
  • REST 和 GraphQL 应用程序接口
  • 实时查询
  • 多种认证选项
  • 可扩展托管
  • 推送和电子邮件通知

Back4App 使用 Parse 服务器,这是一个用于开发应用程序服务器端组件的开源工具包。支持多种技术。本参考指南列出了 Back4app 支持的不同技术。

项目介绍

本指南旨在构建一个 Back4app 后端,以支持 Flutter 应用程序。应用程序将使用 Parse 服务器 SDK 与设置好的后端进行连接和交互。

您要创建的应用程序是一个简单的联系人应用程序,允许用户创建和读取联系人。这些联系人将使用 Back4app 的 PostgreSQL 数据库支持进行存储。

用户只需在应用程序中输入联系人信息,即可添加新联系人。

在本指南结束时,您将对如何做有一个扎实的了解:

  • 在 Back4app 平台上构建后端应用程序
  • 写入结构化的 Back4app 数据库
  • 处理 Parse 后台安全的基础知识。

先决条件

要学习本指南,您必须满足以下前提条件:

  • 熟悉 Dart 语言和 Flutter 框架
  • 在 Flutter 中操作状态的知识
  • 运行应用程序的设备模拟器或模拟器。iOS 的 Xcode 或 Android 的 Android Studio。
  • 基本了解关系型和非关系型数据库

创建应用程序

您需要有一个 Back4app 帐户来创建您的后台。如果您没有账户,可以通过注册免费的 账户来创建。

如果您已经拥有 Back4app 账户,请登录并创建新应用程序。选择 “后台即服务 “作为服务选项。

back4app 创建新应用程序选项类型

这将构建一个可扩展的 BaaS 后端。别忘了给你的应用程序起一个唯一的名字。对于数据库的选择,Back4app 提供 PostgreSQL 作为数据库选项。

PostgreSQL 是一种流行的开源关系数据库管理系统(RDBMS)。它以可扩展性、可靠性、高性能和安全性著称。

使用 Back4app 中的 PostgreSQL 测试版选项,您就可以利用这些功能和优势。

创建新应用程序模式,并输入应用程序名称和 SQL 数据库选项

构建阶段应该很快结束。完成后,您将进入应用程序仪表板。

PostgreSQL 数据库

在 Back4App 中,您可以定义表示应用程序数据的类和字段。PostgreSQL 使用关系数据库,这是一种为应用程序用户存储数据的结构化方法。

如前所述,我们的 Flutter 应用程序将是一个联系人簿,可以存储多个联系人。PostgreSQL 数据库保存关系。该应用程序的合理数据模型是联系人类和联系人的城市邮编。

让我们从联系人模型开始。联系人表需要不同的字段;

  • 联系人 ID/对象 ID
  • 名称
  • 电话号码
  • 邮政编码

您的数据模型表将如下所示;

联系方式

现场数据类型制约因素
contactId整数主键
名字字符串非空
电话号码整数非空
邮政编码POINTER非空

邮政编码

现场数据类型制约因素
对象标识整数主键
邮政编码整数非空

联系人对象将存储联系人信息,并以contactId作为主键。姓名电话号码邮政编码字段必须填写(NOT NULL)、

该数据模型在联系人应用的表之间创建了一种关系,使您能够管理联系人信息,并将多个字段与每个联系人关联起来。

要在 Back4app 应用程序上创建这两个班级,请点击控制面板左上角的 “创建班级“按钮。

在应用程序仪表板中创建类别按钮

将类别命名为 “联系人”,并将 “是否为必填字段“选项切换为 “打开”。

a 创建并添加新列模式

Contact 中的数据字段创建列,然后为ZipCode类创建同样的列。Back4app 允许您自定义创建的每一列。

管理面板

Back4App 提供直观的 GUI(图形用户界面),称为管理面板,可轻松管理应用程序的后台。

管理面板是监控、编辑和分析数据的强大工具,是应用程序管理的宝贵资产。

您可以在应用程序中访问应用程序的管理面板。在应用程序的仪表板上,您会在 “更多“下找到一个标有“管理面板“的按钮或链接,它将引导您进入管理面板。您可以在那里切换并启用管理应用程序。

您将提供一个用户名和密码来访问管理应用程序。

设置管理应用程序的最后一步是选择一个用于访问面板的域名。

在本指南中,一个很好的例子是:flutter-backend.admin.back4app.com

现在,您可以在浏览器上打开提供的域,登录管理仪表板。

要了解有关 Back4app 管理应用程序的更多信息,请访问官方文档

确保应用程序的安全

目前,您的后台应用程序是完全脆弱的,其中的信息可以从客户端进行篡改。

为了防止在生产阶段出现这种情况,可以配置相关规定和访问权限。

要控制类的创建方式并禁止从客户端创建类,请导航至控制面板>应用程序设置并找到客户端类创建。将此选项切换为关闭,因为您的应用程序目前只需要您创建的两个类。

切换关闭时会出现一个弹出窗口。这是为了确认和保存应用程序的更改。

客户端类创建授权的切换开关

使用 Flutter 进行 CRUD API 测试

在本节中,您将使用自己构建的 Flutter 应用程序测试应用程序的后台 API 功能和数据库。首先,您将为 Flutter 应用程序构建用户界面。

您必须在计算机上安装 Flutter SDK 才能初始化 Flutter 应用程序。

按照Flutter 的官方 入门 文档,在 Windows 或 Mac 机器上安装 Flutter SDK 和构建 Flutter 应用程序所需的工具。

要初始化 Flutter 应用程序,请在终端中运行以下命令:

#Initialize your Flutter app
flutter create my_flutter_app

#Run your Flutter app
flutter run

这些命令将搭建并启动一个简单的 Flutter 应用程序,供您构建。

为了保持本指南的简洁性,main.dart文件将包含运行 Flutter 应用程序的大部分代码。我们不会在此讨论 Flutter 代码,因为这不是本指南的目的。

用以下代码覆盖main.dart中的所有代码:

import 'dart:ffi';

import 'package:flutter/material.dart';
import 'package:parse_server_sdk_flutter/parse_server_sdk_flutter.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final keyApplicationId = 'appID';
  final keyClientKey = 'clientKey';
  final keyParseServerUrl = '<https://parseapi.back4app.com>';

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

  runApp(MaterialApp(
    title: 'Contacts',
    theme: ThemeData(
      primaryColor: Colors.white,
    ),
    home: ContactsApp(),
  ));
}

class ContactsApp extends StatefulWidget {
  const ContactsApp({Key? key}) : super(key: key);

  @override
  // ignore: library_private_types_in_public_api
  _ContactsAppState createState() => _ContactsAppState();
}

class _ContactsAppState extends State<ContactsApp> {
  List<Contact> contacts = [];
  String? selectedZipCode; // Initialize with a default value

  @override
  void initState() {
    super.initState();
    selectedZipCode = '1234'; // Initialize with a default value
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Contacts'),
      ),
      body: ListView.builder(
        itemCount: contacts.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(contacts[index].name),
            subtitle: Text(contacts[index].phoneNumber),
            trailing: IconButton(
              icon: const Icon(Icons.delete),
              onPressed: () {
                setState(() {
                  contacts.removeAt(index);
                });
              },
            ),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          _showAddContactDialog();
        },
        child: const Icon(Icons.add),
      ),
    );
  }

  void _showAddContactDialog() async {
    showDialog(
      context: context,
      builder: (context) {
        String name = '';
        String phoneNumber = '';

        return AlertDialog(
          title: const Text('Add Contact'),
          content: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              TextField(
                decoration: const InputDecoration(labelText: 'Name'),
                onChanged: (value) {
                  name = value;
                },
              ),
              TextField(
                decoration: const InputDecoration(labelText: 'Phone Number'),
                onChanged: (value) {
                  phoneNumber = value;
                },
              ),
              // Checkbox for Zip Code
              ListTile(
                title: const Text('Select Zip Code'),
                subtitle: Column(
                  children: [
                    RadioListTile(
                      title: const Text('1234'),
                      value: '1234',
                      groupValue: selectedZipCode,
                      onChanged: (value) {
                        setState(() {
                          selectedZipCode = value;
                        });
                        print(selectedZipCode);
                      },
                    ),
                    RadioListTile(
                      title: const Text('4321'),
                      value: '4321',
                      groupValue: selectedZipCode,
                      onChanged: (value) {
                        setState(() {
                          selectedZipCode = value;
                        });
                        print(selectedZipCode);
                      },
                    ),
                  ],
                ),
              ),
            ],
          ),
          actions: [
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: const Text('Cancel'),
            ),
            ElevatedButton(
              onPressed: () async {
                setState(() {
                  contacts.add(Contact(
                    name: name,
                    phoneNumber: phoneNumber,
                    zipCode: selectedZipCode as String,
                  ));
                });

                // Save the contact to Back4App
                final contact = ParseObject('Contact');
                contact.set('name', name);
                contact.set('phoneNumber', phoneNumber);
                contact.set(
                    'zipCode',
                    (ParseObject('ZipCode')..objectId = selectedZipCode.objectId)
                        .toPointer());

                await contact.save();

                // ignore: use_build_context_synchronously
                Navigator.of(context).pop();
              },
              child: const Text('Save'),
            ),
          ],
        );
      },
    );
  }
}

class Contact {
  final String name;
  final String phoneNumber;
  final String zipCode;

  Contact({
    required this.name,
    required this.phoneNumber,
    required this.zipCode,
  });
}

class ZipCode {
  final String zipCode;

  ZipCode({
    required this.zipCode,
  });
}

这样,您的 Flutter 应用程序的基本 UI 就可以运行了。

现在你可以开始实施 Back4app 了。Back4app 使用 Parse Flutter SDK 将 Parse 服务器集成到 Flutter 应用程序中。

Parse Server 是一个开源后端平台,为管理应用程序数据提供了一个即用型基础架构。

有了 SDK,您就可以通过 Flutter 应用程序与 Parse Server API 通信,从而更轻松地对数据执行 CRUD 操作(创建、读取、更新、删除)、管理用户会话以及处理其他服务器端功能。

要使用 Parse SDK,请将其作为依赖项安装到 Flutter 项目的pubspec.yaml文件中。

指定Parse服务器:

dependencies:
	# Parse SDK
  parse_server_sdk_flutter: ^5.1.1

  flutter:
    sdk: flutter

确保缩进准确。.yaml文件对大小写和缩进非常敏感。

运行命令安装指定的依赖项:

flutter pub get

前往main.dart,导入添加的 Parse SDK:

import 'package:parse_server_sdk_flutter/parse_server_sdk_flutter.dart';

void main() async{
  WidgetsFlutterBinding.ensureInitialized();
	// code for runApp()

  const keyApplicationId = 'YOUR_APPLICATION_ID_HERE';
  const keyClientKey = 'YOUR_CLIENT_KEY_HERE';
  const keyParseServerUrl = '<https://parseapi.back4app.com>';

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

在这里,你要将 ParseSDk 导入你的main.dart文件。你还需要在main()中调用Parse().initialize()来初始化Parse。由于这是一个异步程序,所以要用 async 关键字标记main()

必须用实际值替换Application_IdClient Key的占位符。这些是与后端通信的应用程序凭据。

要获取这些密钥,请从 Back4app 面板导航至应用程序设置>安全与密钥。然后用相应的密钥替换占位符。

运行应用程序时,main()将被触发,Parse 将初始化您的应用程序,您的 Flutter 应用程序将连接到 Back4app 后端。

写入联系人和邮政编码类

在这里,您将学习如何从应用程序的客户端创建数据库中的类并写入这些类。要创建 “联系人 “和 “生日 “类,您需要修改main.dart 文件。

在高架按钮部件的onPressed()方法中,您将使用ParseObject()创建一个联系人 类的新实例:

final contact = ParseObject('Contact');
contact.set('name', name);
contact.set('phoneNumber', phoneNumber);

final ParseResponse parseResponse = await contact.save();

if (parseResponse.success) {
   final contactId = (parseResponse.results!.first as ParseObject).objectId!;
		print('Object created: $contactId');

	} else {
      print('Object created with failed: ${parseResponse.error.toString()}');
    }

Parse Flutter SDK 会使用ParseObject()创建一个新实例,该实例与您作为参数传递的类名相同。使用对象字段的名称及其值调用Contact.set()将写入并更新这些字段。

您可以创建一个ParseResponse对象来保存保存操作的结果。ParseResponse将包含一个success属性,如果保存操作成功,则该属性为true;如果保存操作失败,则该属性为false

然后,代码会将变量contactId初始化为空。该变量将用于存储自动生成的已保存联系人对象的objectId。然后进行一些错误处理。

在上述代码下方

final zipCodeObject = ParseObject('ZipCode')
    ..objectId = selectedZipCode as String;
zipCodeObject.set('zipCode', selectedZipCode);
contact.set('zipCode', zipCodeObject.toPointer());

await contact.save();
await zipCodeObject.save();

在此创建邮编 ParseObject。当通过对话框添加新联系人时,代码将正确创建一个ZipCode对象,并将其与联系人对象的zipCode字段关联。

它使用所选邮编的objectId作为指针建立关联。使用.save()方法将两个对象保存到后台。

从数据库中查询/读取数据

下面我们将讨论如何从 Flutter 应用程序向数据库发送查询。您可以进行查询,检索具有相同邮政编码的所有联系人。在非关系型数据库系统中,要实现这一点相当复杂。

如果检索成功,就可以显示 Flutter 应用程序中所有联系人的列表。

检索具有相同邮政编码的联系人列表:

Future<void> _loadContacts() async {
  final queryBuilder = QueryBuilder<ParseObject>(ParseObject('Contact'))
    ..whereEqualTo('zipCode', selectedZipCode) // Filter by zip code
    ..orderByAscending('name');

  final response = await queryBuilder.query();

  if (response.success && response.results != null) {
    final List<Contact> loadedContacts = response.results!.map((parseObject) {
      return Contact(
        name: parseObject.get('name'),
        phoneNumber: parseObject.get('phoneNumber'),
        zipCode: parseObject.get('zipCode')!.objectId,
      );
    }).toList();

    setState(() {
      //set your contacts to loadedContacts
    });
  }
}

@override
  void initState() {
    super.initState();
   
    _loadContacts(); // Load contacts when the app starts
  }

_loadContacts方法向联系人类建立一个查询,查找具有指定邮政编码的联系人对象。

然后,该方法会返回联系人列表,同时根据 “姓名 “字段按姓名升序排列。

应用程序启动时(initState),会调用_loadContacts方法来获取所选邮编的联系人。

结论

拥有一个可控的后端绝对是必要的,在这里您可以正确构建应用程序中的数据流。使用 Back4app,您可以随时随地建立移动应用程序的后台。

您还可以使用 Back4app 平台,通过设置用户模型数据库来实现用户身份验证。

什麼是 Flutter?

Flutter 是一個開發框架,可用於建立跨多個平台的類原生應用程式。它簡化了建立特定平台應用程式的流程,並以快速的開發速度和漂亮的使用者介面而聞名。

後端部署有哪些選項?

IaaS(基礎設施即服務)
PaaS(平台即服務)
BaaS(後端即服務)

如何建立一個 Flutter 應用的後端?

1. 規劃應用程式的資料模型結構
2. 設置一個資料庫來對應這個結構
3. 撰寫 UI 檢視邏輯並連接後端
4. 測試後端的安全性漏洞並執行 CRUD 操作
5. 選擇一個部署平台,例如 Back4app
6. 將你的應用程式部署到後端


Leave a reply

Your email address will not be published.