共计 5902 个字符,预计需要花费 15 分钟才能阅读完成。
一、背景
微信小程序倒退的越来越快,目前小程序甚至取代了大部分 App 的生态位,公司的坑位不增反降,只能让原生利用开发兼顾或换岗进行小程序的开发。
以我的理论状况来讲,公司利用采纳的 Flutter 框架,同样的性能不可避免的就会存在 Flutter 利用开发和微信小程序开发兼顾的状况,这种反复造轮子的工作十分低效。
为什么会呈现这种状况呢?随着 2019 年 5 月 Google I/O 上 Flutter 1.5.4 的公布,宣示着 Flutter 真正开始进入全终端时代,意味着只须要写一份代码,不须要任何额定的修改改,就能够运行在 iOS、Android、Web、PC 上。Flutter 正在革命性的扭转挪动开发的生态系统,从面向各个终端的开发,转向面向框架开发,不仅会扭转开发者的开发方式,也有越来越多的公司开始关注应用 Flutter。
Flutter 作为一个跨平台的框架,其开发技术栈交融了 Native 和前端的技术,不仅波及到了 Native(Android、iOS)的开发常识,又汲取了很多前端(例如 React)的技术理念和框架,并且在此基础上又有晋升,造成 Flutter 本人独特的技术思维。
但目前来讲,Flutter 并不反对小程序,Flutter for Web 尽管最初也会生成 JS 代码,然而 Flutter 生成的 JS 和 CSS 都是不能批改的。而在 Flutter 中也没方法通过 Dart 间接调用小程序的接口,所以现阶段用 Flutter 开发小程序不是太好的抉择。
二、一些解决思路
事实上,随着小程序这种轻量级终端的呈现,公司和业务也不得不向着互联网巨头的流量抬头,同时小程序的逐步风靡,也使得用户下载 App 的习惯产生了变动。不论购物、订餐还是办事,人们都会首先查找“关上即用,即用即走”的小程序,省去了下载 App 的繁琐流程。
当然也晓得很多开发者对于小程序是有十分多意见的,App 也不会说死就死,毕竟 App 绝对于小程序来讲,还是有很多劣势。所以 App 和小程序开发都共存的状况下,如何解决效率问题?是否让过往开发的小程序间接运行在 Flutter 开发的利用中呢?同样一个性能业务仅需一次小程序开发,即可实现在除了微信端的其它 App 中也运行起来。
在 Google 找相干的解决方案和材料的时候,发现国外简直没有这种计划,国内倒是有厂商在做这块,想想也的确合乎情理。基于公司 Flutter 框架的根底现实情况下,名为 FinClip 小程序容器技术的产品是可能反对除原生 iOS、Android 之外的 Flutter 和 React Native,于是大略测试了下这个产品。
三、FinClip 实操
原理其实挺简略的,FinClip 提供了小程序 SDK 给 Flutter 利用进行集成,这样以来 App 即领有了一套可运行小程序业务代码的宿主环境,原理示意图如下。
3.1 获取凭据
集成 SDK 须要在 FinClip 平台中创立利用并绑定小程序,取得每个利用专属的 SDK KEY 及 SDK SECRET,随后能够在集成 SDK 时填写对应的参数。关上小程序时 SDK 会主动初始化,并校验 SDK KEY、SDK SECRET 与 BundleID (Application ID) 是否正确。
3.2 集成插件
首先,关上 Flutter 我的项目,而后在我的项目的 pubspec.yaml 文件中增加依赖。
mop: latest.version
依赖阐明参考:https://pub-web.flutter-io.cn/packages/mop
如果电脑是 mac M1 芯片,还须要在 iOS 文件夹的 Podfile 文件减少以下 3 行代码:
config.build settings ['ENABLE BITCODE'] = 'NO'
config.build settings ['IPHONEOS DEPLOYMENT TARGET'] = 19.0'config.build settings ['EXCLUDED ARCHS (sdk=iphonesimulator*]'] ='arm64 1386'
依赖示例如下:
3.3 Flutter API
在集成 mop 插件后,应用 SDK 提供的 API 之前必须要初始化 SDK。上面我列举官网的一些必要的 API,更具体的也能够查阅官网文档。
1,初始化 sdk 接口
在应用 sdk 提供的 api 之前必须要初始化 sdk,初始化 sdk 的接口为:
///
///
/// initialize mop miniprogram engine.
/// 初始化小程序
/// [sdkkey] is required. it can be getted from api.finclip.com
/// [secret] is required. it can be getted from api.finclip.com
/// [apiServer] is optional. the mop server address. default is https://mp.finogeek.com
/// [apiPrefix] is optional. the mop server prefix. default is /api/v1/mop
/// [cryptType] is optional. cryptType, should be MD5/SM
/// [disablePermission] is optional.
/// [encryptServerData] 是否对服务器数据进行加密,须要服务器反对
/// [userId] 用户 id
/// [finStoreConfigs] 多服务配置
/// [uiConfig] UI 配置
/// [debug] 设置 debug 模式,影响调试和日志
/// [customWebViewUserAgent] 设置自定义 webview ua
/// [appletIntervalUpdateLimit] 设置小程序批量更新周期
/// [maxRunningApplet] 设置最大同时运行小程序个数
///
Future<Map> initialize(
String sdkkey,
String secret, {
String? apiServer,
String? apiPrefix,
String? cryptType,
bool encryptServerData = false,
bool disablePermission = false,
String? userId,
bool debug = false,
bool bindAppletWithMainProcess = false,
List<FinStoreConfig>? finStoreConfigs,
UIConfig? uiConfig,
String? customWebViewUserAgent,
int? appletIntervalUpdateLimit,
int? maxRunningApplet,
})
应用示例:
final res = await Mop.instance.initialize(
'22LyZEib0gLTQdU3MUauARlLry7JL/2fRpscC9kpGZQA', '1c11d7252c53e0b6',
apiServer: 'https://api.finclip.com', apiPrefix: '/api/v1/mop');
2,关上小程序
/// open the miniprogram [appId] from the mop server.
/// 关上小程序
/// [appId] is required.
/// [path] is miniprogram open path. example /pages/index/index
/// [query] is miniprogram query parameters. example key1=value1&key2=value2
/// [sequence] is miniprogram sequence. example 0,1.2.3,4,5...
/// [apiServer] is optional. the mop server address. default is https://mp.finogeek.com
/// [apiPrefix] is optional. the mop server prefix. default is /api/v1/mop
/// [fingerprint] is optional. the mop sdk fingerprint. is nullable
/// [cryptType] is optional. cryptType, should be MD5/SM
Future<Map> openApplet(
final String appId, {
final String? path,
final String? query,
final int? sequence,
final String? apiServer,
final String? scene,
})
3,获取小程序信息
以后小程序信息,包含的字段有 appId、name、icon、description、version、thumbnail 等。
///
/// get current using applet
/// 获取以后正在应用的小程序信息
/// {appId,name,icon,description,version,thumbnail}
///
///
Future<Map<String, dynamic>> currentApplet()
4,敞开小程序
///
/// close all running applets
/// 敞开以后关上的所有小程序
///
Future closeAllApplets()
5,清理小程序
革除缓存的小程序,当再次关上时,会从新下载小程序。
///
/// clear applets cache
/// 革除缓存的小程序
///
Future clearApplets()
3.4 官网示例
上面是官网提供的一段示例代码。
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:io';
import 'package:mop/mop.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {super.initState();
init();}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> init() async {if (Platform.isiOS) {
//com.finogeeks.mopExample
final res = await Mop.instance.initialize(
'22LyZEib0gLTQdU3MUauARlLry7JL/2fRpscC9kpGZQA', '1c11d7252c53e0b6',
apiServer: 'https://api.finclip.com', apiPrefix: '/api/v1/mop');
print(res);
} else if (Platform.isAndroid) {
//com.finogeeks.mopexample
final res = await Mop.instance.initialize(
'22LyZEib0gLTQdU3MUauARjmmp6QmYgjGb3uHueys1oA', '98c49f97a031b555',
apiServer: 'https://api.finclip.com', apiPrefix: '/api/v1/mop');
print(res);
}
if (!mounted) return;
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('凡泰极客小程序 Flutter 插件'),
),
body: Center(
child: Container(
padding: EdgeInsets.only(top: 20,),
child: Column(
children: <Widget>[
Container(
decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(5)),
gradient: LinearGradient(colors: const [Color(0xFF12767e), Color(0xFF0dabb8)],
stops: const [0.0, 1.0],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
child: FlatButton(onPressed: () {Mop.instance.openApplet('5e3c147a188211000141e9b1');
},
child: Text(
'关上示例小程序',
style: TextStyle(color: Colors.white),
),
),
),
SizedBox(height: 30),
Container(
decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(5)),
gradient: LinearGradient(colors: const [Color(0xFF12767e), Color(0xFF0dabb8)],
stops: const [0.0, 1.0],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
child: FlatButton(onPressed: () {Mop.instance.openApplet('5e4d123647edd60001055df1',sequence: 1);
},
child: Text(
'关上官网小程序',
style: TextStyle(color: Colors.white),
),
),
),
],
),
),
),
),
);
}
}
而后,我装置到真机上测试了一下,体验还不错。
参考文档:https://pub-web.flutter-io.cn/packages/mop