【玩转腾讯云】万物皆可Serverless之在Flutter中快速接入腾讯云开发

万物皆可Serverless系列文章

一、本文介绍

云开发(Tencent Cloud Base,TCB)是腾讯云为移动开发者提供的高可用、自动弹性扩缩的后端云服务,包含计算、存储、CDN、静态托管等能力(Serverless 化),可用于开发多种端应用(小程序,公众号,Web 应用,Flutter 客户端等,后续会陆续支持 iOS 和 Android 等移动应用开发),达到一站式后台服务构建多端应用,帮助开发者统一构建和管理后端服务和后端云资源,避免了应用开发过程中参与繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。

这是腾讯云官方文档的里的关于云开发的简介,

本文将带领大家按照云开发的官方文档在Flutter中快速接入一下腾讯云开发SDK,

废话少说,上图

Flutter接入云开发demo

二、开始教程

第一步:添加依赖

dependencies:
  flutter:
    sdk: flutter
  file_picker: ^1.6.3+2
  cloudbase_core: ^0.0.4
  cloudbase_auth: ^0.0.5
  cloudbase_function: ^0.0.2
  cloudbase_storage: ^0.0.2
  cloudbase_database: ^0.0.7

注意,这里的file_picker只是用来在测试云开发对象存储文件上传时选择本地文件用的,与云开发无关

配置好后记得下载安装一下依赖

flutter pub get

第二步:导入依赖

自己按需导入哈

import 'package:cloudbase_core/cloudbase_core.dart';
import 'package:cloudbase_auth/cloudbase_auth.dart';
import 'package:cloudbase_function/cloudbase_function.dart';
import 'package:cloudbase_storage/cloudbase_storage.dart';
import 'package:cloudbase_database/cloudbase_database.dart';

第三步:云开发实例

准备工作

我们先去云开发后台配置一下自己的云开发环境

新建一个云函数

这里我们新建了一个名为 addOne 的 Nodejs 云函数,来测试Flutter调用云函数实现简单加法

配置云数据库

接着我们来到云开发数据库,新建一个名为 letters 的测试文档集,并添加一条测试数据

公有读私有写

配置一下 letters 文档集的访问权限,方便一会我们在Flutter端匿名登陆云开发环境,正常获取到文档数据

OK,到这里云开发测试环境的准备工作就做好了。

示例程序

Life is short, show me the code.

话不多说,上代码

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
import 'package:cloudbase_core/cloudbase_core.dart';
import 'package:cloudbase_auth/cloudbase_auth.dart';
import 'package:cloudbase_function/cloudbase_function.dart';
import 'package:cloudbase_storage/cloudbase_storage.dart';
import 'package:cloudbase_database/cloudbase_database.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter接入腾讯云开发',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter接入腾讯云开发'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  bool flag = false;
  String filePath = '';
  List dbDocuments = [];
  CloudBaseCore core;
  CloudBaseAuth auth;
  CloudBaseDatabase db;
  CloudBaseStorage storage;
  CloudBaseFunction cloudbase;

  ///加号按钮点击事件
  void _incrementCounter() async {
    if (!flag) return;
    //调用云函数+1
    CloudBaseResponse res =
        await cloudbase.callFunction('addOne', {'num': _counter});
    setState(() {
      _counter = res.data['result'];
    });
  }

  ///将本地文件上传到cos
  upload() async {
    File file = await FilePicker.getFile();
    if (file != null) {
      await storage.uploadFile(
          cloudPath: file.path.split("/").last, filePath: file.path);
      setState(() {
        filePath = file.path.split("/").last;
      });
    }
  }

  ///查询云数据库文档
  getDocument() async {
    db
        .collection('letters')
        .where({'date': '2020-04-20'}) //获取date日期为2020-04-20的文档
        .get()
        .then((res) {
          setState(() {
            dbDocuments = res.data;
          });
        })
        .catchError((e) {
          print('获取文档失败');
        });
  }

  ///初始化云开发
  init() async {
    // 初始化
    core = CloudBaseCore.init({'env': 'xxxxx-xxxxxx'});
    // 获取登录对象
    auth = CloudBaseAuth(core);
    // 唤起匿名登录
    await auth.signInAnonymously().then((success) async {
      // 登录成功
      db = CloudBaseDatabase(core); //初始化数据库
      storage = CloudBaseStorage(core); //初始化对象存储
      cloudbase = CloudBaseFunction(core); //初始化云函数
      setState(() {
        flag = true;
      });
      print('登录成功');
    }).catchError((err) {
      // 登录失败
      setState(() {
        flag = false;
      });
      print('登录失败');
    });
  }

  @override
  void initState() {
    super.initState();
    Future.delayed(Duration.zero, () async {
      await init();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        actions: <Widget>[
          Builder(
            builder: (BuildContext context) {
              return PopupMenuButton(
                  onSelected: (String value) async {
                    switch (value) {
                      case "上传":
                        await upload();
                        break;
                      case "查询":
                        await getDocument();
                        break;
                    }
                  },
                  itemBuilder: (BuildContext context) =>
                      <PopupMenuItem<String>>[
                        PopupMenuItem(value: "上传", child: Text("对象存储->上传文件")),
                        PopupMenuItem(value: "查询", child: Text("云数据库->查询数据")),
                      ]);
            },
          )
        ],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            Offstage(
                offstage: filePath.length < 1,
                child: Text(
                  '文件已上传(来自对象存储)\n' + filePath,
                )),
            Text(
              dbDocuments.length > 0
                  ? '获取到${dbDocuments.length}个文档(来自云数据库)\n' +
                      dbDocuments.first['letter']
                  : '',
            ),
            Text(
              '你点击了$_counter次加号(来自云函数)',
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        child: Icon(Icons.add),
      ),
    );
  }

  @override
  void dispose() async {
    super.dispose();
    //退出登录
    await auth?.signOut();
  }
}

首先我们在当前页面加载时,初始化一下自己的云开发环境

  ///初始化云开发
  init() async {
    // 初始化
    core = CloudBaseCore.init({'env': 'xxxxx-xxxxxx'});//这里要填上自己的云开发环境id
    // 获取登录对象
    auth = CloudBaseAuth(core);
    // 唤起匿名登录
    await auth.signInAnonymously().then((success) async {
      // 登录成功
      db = CloudBaseDatabase(core); //初始化数据库
      storage = CloudBaseStorage(core); //初始化对象存储
      cloudbase = CloudBaseFunction(core); //初始化云函数
      setState(() {
        flag = true;
      });
      print('登录成功');
    }).catchError((err) {
      // 登录失败
      setState(() {
        flag = false;
      });
      print('登录失败');
    });
  }

然后来看一下点击加号按钮会触发的_incrementCounter函数

  ///加号按钮点击事件
  void _incrementCounter() async {
    if (!flag) return;
    //调用云函数+1
    CloudBaseResponse res =
        await cloudbase.callFunction('addOne', {'num': _counter});
    setState(() {
      _counter = res.data['result'];
    });
  }

这里我们是直接调用了前面设置好的云函数 addOne 来实现 _counter 的增加功能,来测试云开发调用云函数的能力

  ///将本地文件上传到cos
  upload() async {
    File file = await FilePicker.getFile();
    if (file != null) {
      await storage.uploadFile(
          cloudPath: file.path.split("/").last, filePath: file.path);
      setState(() {
        filePath = file.path.split("/").last;
      });
    }
  }

  ///查询云数据库文档
  getDocument() async {
    db
        .collection('letters')
        .where({'date': '2020-04-20'}) //获取date日期为2020-04-20的文档
        .get()
        .then((res) {
          setState(() {
            dbDocuments = res.data;
          });
        })
        .catchError((e) {
          print('获取文档失败');
        });
  }

然后再来点击程序右上角的Popmenu来测试下Flutter使用云开发上传cos文件和查询云开发数据库文档的能力

测试正常

一切正常,这样就在Flutter里接入好腾讯云云开发了。

第四步:实名表(tu)扬(cao)官方文档

没错,这里我要专门用一个段落来表扬吐槽云开发的文档,

无图无真相,上图

云开发文档

当时是在2020年3月16号,我需要给自己的应用接入云数据库,就在找云开发Flutter SDK文档

然后看到这里只有登录鉴权、云函数和对象存储的插件,自己心里就凉了一半~

准备提issue

无奈,自己甚至想到云开发官方团队仓库下面准备提issue,然后想或许pub.dev里会有云数据库的第三方库

云开发数据库插件

还真被我找到了,

原来云开发数据库的官方Flutter SDK是在3月13日刚刚发布的,官方文档可能还没来得及更新,

你以为这就完了?没有,我再举几个例子

我不是来专门找茬的哈,只是觉得把官方文档里的示例代码复制到自己的编辑器里就报错,这个体验很不爽嘛~

云开发的官方文档有很多细节的地方会有小错误,

虽然这些小细节的地方无关紧要,但是让人觉得不够严谨,不像是一份官方文档该有的样子。

云开发下的云函数只有nodejs和php运行环境

还有一个地方,我搞不大明白,

为什么云开发里面的云函数环境只有Nodejs和php?

难道这里的云函数和腾讯云里单独的云函数业务环境是分离的?

我想可能这个云开发的定位之前是小程序,走的还是前端网页开发那一套,所以只用Nodejs和php环境就可以了,

但是现在云开发的使用场景已经布局到了移动端,这样的话只有js和php这两个语言环境就有点不大够用了

真的是强烈希望云开发的团队可以把云函数的运行环境支持java,pyhton,golang之类,就像独立的云函数那样

这样云开发的全端开发体验就真的无敌,真香了~

独立的云函数运行环境支持nodejs、php、python、java和golang

总之云开发Flutter SDK才刚刚开始发布嘛,

文档这一块可能没有仔细检查或者跟上更新进度之类,

这个大家还是要多多见谅,开发者自己多注意一下,

然后衷心祝愿腾讯云云开发能够越来越强大,越来越好,为更多开发者带来便利服务。

云开发,加油鸭!

三、文章最后

如果你有了解我之前的系列文章的话,

你应该晓得我是比较喜欢SCF+COS这个组合来搞全栈应用的,

当然这种方式只是适合一些简单数据的增删查改,功能比较鸡肋。

现在我的需求是给自己的Flutter应用做一个完备的用户管理系统,

这种情况的话,使用云开发会是一个不错的选择。

所以今天我终于上了云开发的车,

因为云开发基础版套餐是有免费额度的,

哈哈哈哈,穷就一个字,我只说一次XD

逃~

admin
admin管理员

上一篇:【玩转腾讯云】【腾讯云语音识别】如何在微信小程序中进行接口鉴权
下一篇:数据迁移与一致性思考与实践

留言评论

暂无留言