关键词:
前言
为了迎合新技术,并且可以一端开发两端受用,于是乎在引入新的功能模块的时候,尝鲜使用flutter来进行开发。众所周知,在尝鲜新技术的时候总会有种畏惧感,人类总是喜欢使用熟悉的东西,而作为程序员更加喜欢用自己擅长的技术,但纵使有千般难,万般坑,既然选择了,总要把他跨过,踩完。
1. Flutter工程介绍
1.1 模块介绍
目前工程包括基础模块和kds模块,两个模块都是单独的plugin,并且test依赖base插件。
- CCDFlutterBase – flutter基础模块,包括
- channel ---- 通信相关
- data ---- 数据
- int ---- 国际化
- network ---- 网络请求封装
- res ---- color,style等资源
- sp ---- 存储
- utils ---- 工具类
- widget ---- 一些公用的widget
- CCDTest – 相关业务
考虑到后续flutter工程会越来越多,所以使用repo来统一管理flutter工程。
1.2 flutter boost
为了原生和flutter路由跳转的方便,这里引入了闲鱼的开源项目flutter_boost。
对kds工程做了如下方式的修改,在单独运行的时候可以选择需要运行的页面,比如使用KdsOrder(),而在打包的时候,需要使用MyApp(),这个需要手动修改。
void main() => runApp(MyApp());
//void main() => runApp(Order());
//void main() => runApp(Setting());
class MyApp extends StatefulWidget
@override
_MyAppState createState() => _MyAppState();
class _MyAppState extends State<MyApp>
@override
void initState()
super.initState();
///register page widget builders,the key is pageName
FlutterBoost.singleton.registerPageBuilders(
'ccd://Order': (pageName, params, _) => KdsOrder(),
'ccd://Setting': (pageName, params, _) => KdsSetting(),
);
///query current top page and load it
FlutterBoost.handleOnStartPage();
@override
Widget build(BuildContext context) => MaterialApp(
title: 'Flutter CloudCashDesk',
builder: FlutterBoost.init(),
///init container manager
home: Container());
1.3 通信
获取原生中的数据,暂时比较简单,只需要网络请求的数据,后续两边的交互,事件的触发,需要加更多的功能。
/// 获取sp信息,实时等待,调用方法:
/// UserModel userModel = await CCDMethodChannel.getUserInfo();
static Future<UserModel> getUserInfo() async
try
final String result =
await methodChannel.invokeMethod(ChannelConstant.get_user_info);
Map map = json.decode(result);
if (map == null) return null;
return UserModel.fromJson(map);
on PlatformException
print('Failed to get user.');
return null;
1.4 国际化
MaterialApp中加入国际化配置
//国际化
locale: _locale,
localizationsDelegates: [
CustomLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
//dialog
const FallbackCupertinoLocalisationsDelegate()
],
supportedLocales: CustomLocalizations.supportedLocales,
若使用了cupertino dialog需要加入
class FallbackCupertinoLocalisationsDelegate
extends LocalizationsDelegate<CupertinoLocalizations>
const FallbackCupertinoLocalisationsDelegate();
@override
bool isSupported(Locale locale) => true;
@override
Future<CupertinoLocalizations> load(Locale locale) =>
DefaultCupertinoLocalizations.load(locale);
@override
bool shouldReload(FallbackCupertinoLocalisationsDelegate old) => false;
定义String
class Ids
static String test1 = 'test1';
static String test2 = 'test2';
/// 简单多语言资源.
Map<String, Map<String, String>> localizedSimpleValues =
// 'en':
// Ids.test1: 'test1',
// Ids.test2: 'test2',
// ,
'zh':
Ids.test1: '测试1',
Ids.test2: '测试2',
,
;
在代码中引用string
IntlUtil.getString(context, Ids.test1)
1.5 网络
-
dio,只需要传入对应的网络api接口名和参数
-
charles代理设置
因为dio的网络请求默认不走设置中的代理,所以需要设置代理的ip地址和端口,一般默认端口8888,所以只需要设置ip地址,由于不同人使用的charles地址不一样,需要有一个设置入口,存储方式如下:
SpUtil.putString(SpHelper.charlesIp, ip_addr);
这里提供一个dialog用于设置代理ip
DialogUtils.showCharlesIpAddrDialog
1.6 资源文件
资源文件包括常用的颜色,字体大小和样式等。
使用方式,比如字体颜色是#333的使用
CCDColor.text_333
字体大小是15sp
Dimens.font_sp15
样式类型是列表的描述
CCDTextStyles.listDesc
1.7 存储
初始化
await SpUtil.getInstance();
存储用户数据
UserModel userModel = await CCDMethodChannel.getUserInfo();
SpHelper.putObject<UserModel>(SpHelper.userInfo, userModel);
获取用户数据
UserModel userModel = SpHelper.getObject<UserModel>(SpHelper.userInfo);
2. Android引入方式
Flutter有多种引入方式,常见的是:
- 源码集成:使用flutter modle方式将flutter整体框架依赖和打包脚本都集成到主项目中。
- aar集成:把所有的项目都以aar的完整库集成形式添加到主项目。
第一种方式虽然编译运行非常方便,但是会对主工程有侵入。
第二种方式flutter独立运行,最终所有代码和资源打包后依赖,对主工程无任何的侵入,但是调试两端通信会比较不方便。
考虑到不是所有的同学都在本地安装了flutter,并且jenkins打包也可能会遇到问题,这里采用第二种aar的方式。
3. Android打包实现
考虑到flutter的独立运行和打包两种方式的共同体存在,使用gradle.properties添加变量FLUTTER_AAR控制来实现:
FLUTTER_AAR = false
默认是flutter以apk方式运行,如需打包,则只要修改其变量为true即可打包上传到nexus仓库,并可以在android项目中直接引用。
- 修改app的build.gradle
区分指定类型
if (FLUTTER_AAR == "true")
apply plugin: 'com.android.library'
else
apply plugin: 'com.android.application'
区分applicationid
if (FLUTTER_AAR == "false")
applicationId "com.zmsoft.flutter.kds.kds_example"
区分AndroidManifest
if (FLUTTER_AAR == "false")
sourceSets
main
manifest.srcFile "src/main/AndroidManifest.xml"
else
sourceSets
main
manifest.srcFile "src/main/library/AndroidManifest.xml"
由于flutter工程会依赖第三方插件,在android中引入nexus的时候会出依赖相关的问题,所以这里使用fat-aar把所有依赖的工程打成一个aar的包。所以需要做如下修改:
工程的build.gradle中buildscript的dependencies中添加
if (FLUTTER_AAR == "true")
classpath 'com.kezong:fat-aar:1.1.7'
app的build.gradle中加入:
apply plugin: 'com.kezong.fat-aar'
app的build.gradle的dependencies添加
if (FLUTTER_AAR == "true")
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists())
pluginsFile.withReader('UTF-8') reader -> plugins.load(reader)
plugins.each name, _ ->
println name
embed project(path: ":$name", configuration: 'default')
至此可以实现apk和aar的两种方式切换
- 上传nexus仓库
这里为了方便开发先使用本地的url
def mavenRepositoryUrl = 'file:///Users/jaredchen/Documents/repo'
def NEXUS_USERNAME = 'xxxxx'
def NEXUS_PASSWORD = 'xxxxx
uploadArchives
repositories.mavenDeployer
repository(url: mavenRepositoryUrl)
authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD)
pom.groupId = 'com.test.modlue'
pom.artifactId = 'my-flutter'
pom.version = '1.0.1'
pom.whenConfigured pom ->
pom.dependencies.remove(pom.dependencies.find dep -> dep.artifactId == 'shared_preferences' )
pom.dependencies.remove(pom.dependencies.find dep -> dep.artifactId == 'base_app_flutter' )
pom.dependencies.remove(pom.dependencies.find dep -> dep.artifactId == 'test' )
pom.dependencies.remove(pom.dependencies.find dep -> dep.artifactId == 'xservice_kit' )
pom.dependencies.remove(pom.dependencies.find dep -> dep.artifactId == 'flutter_boost' )
因为是把所有的plugin打包成一个aar,这里需要去除对应模块的pom依赖,要不然依赖会有各种问题。
至此可以实现aar的发布。
4. Android使用方式
- 在build.gradle中引用远程的aar包
implementation 'com.test.modlue:my-flutter:1.0.1'
- flutter boost
class FlutterSetting : BoostFlutterActivity(), CCDMethodChannel.ChannelInterface
override fun getContainerParams(): MutableMap<Any?, Any?>?
return null
override fun getContainerName(): String
return FlutterRouterConstant.FlutterKDSSetting.ContainerName
override fun onRegisterPlugins(p0: PluginRegistry?)
GeneratedPluginRegistrant.registerWith(p0)
CCDMethodChannel.getInstance().setChannelInterface(this)
override fun getUserInfo(): String
return FlutterChannelHelper.getUserInfo()
这里只需要return在flutter工程中的containername。就可以渲染flutter中编写好的代码,当然也支持fragment。
android开发学习之路--react-native混合开发初体验
准备node安装:https://nodejs.org/en/react-native官网:https://facebook.github.io/react-native/TypeScript:http://www.typescriptlang.org/docs/home.html1.Expo尝鲜1.1环境安装:1.1.1npm来安装create-reac 查看详情
flutterflutter混合开发(混合开发中flutter的热重启/热加载)(代码片段)
...递数据|FlutterFragment数据传递|FlutterActivity数据传递)讲解了Android如何向Flutter中传递数据;Flutter混合开发集成步骤 查看详情
flutter混合开发:android中如何启动flutter(代码片段)
...何启动flutter页面,及flutter与native如何交互。本文以Android为例,展 查看详情
flutter混合开发:android中如何启动flutter(代码片段)
...何启动flutter页面,及flutter与native如何交互。本文以Android为例,展示如何在一个现有项目中引入flutter、启动fl 查看详情
flutter混合开发之flutterfragment
我们知道,原生Android集成Flutter主要有两种方式,一种是创建fluttermodule,然后以原生module那样依赖;另一种方式是将fluttermodule打包成aar,然后在原生工程中依赖aar包,官方推荐aar的方式接入。如何在原生Android工程中以aar的方式... 查看详情
原生android集成flutter混合开发(代码片段)
原生Android和Flutter集成主要有两种方案:1.源码集成:官方提供的源码集成方案2.产物集成:Flutter项目单独开发,开发完成后发布成aar包或者iOS的framework形式,原生项目依赖Flutter输出的文件即可。3.咸鱼团队的F... 查看详情
flutterflutter混合开发(flutter与native通信|android端实现methodchannel通信)(代码片段)
文章目录前言一、Android端MethodChannel构造函数二、Android端setMethodCallHandler方法三、Android端实现MethodChannel通信步骤四、相关资源前言本博客与【Flutter】Flutter混合开发(Flutter与Native通信|在Flutter端实现MethodChannel通信)博客相对应,该... 查看详情
flutterflutter混合开发(flutter与native通信|android端实现eventchannel通信)(代码片段)
文章目录前言一、Android端EventChannel构造函数二、Android端setStreamHandler方法三、Android端实现EventChannel通信步骤四、Android端与Flutter端EventChannel注册与监听流程五、相关资源前言本博客与【Flutter】Flutter混合开发(Flutter与Native通信|在F... 查看详情
flutterflutter混合开发(flutter与native通信|android端实现basicmessagechannel通信)(代码片段)
文章目录前言一、Android端BasicMessageChannel构造函数二、Android端MessageCodec子类实现三、Android端setMessageHandler方法四、Android端send方法五、Android端实现BasicMessageChannel通信步骤六、相关资源前言本博客与【Flutter】Flutter混合开发(Flutter... 查看详情
flutter混合开发(代码片段)
1、用AndroidStudio在上一篇的文档目录下创建安卓项目 FlutterHybridAndroid2、在已创建好的项目中找到, 添加setBinding(newBinding([gradle:this]))evaluate(newFile(settingsDir.parentFile,\'flutter_module/.android/include_flutter.groov 查看详情
flutterflutter混合开发(flutter与native通信|完整代码示例)(代码片段)
文章目录前言一、Android端完整代码示例二、Flutter端完整代码示例三、相关资源前言前置博客:【Flutter】Flutter混合开发(Flutter与Native通信|在Flutter端实现BasicMessageChannel通信)【Flutter】Flutter混合开发(Flutter与Native通信|在Flutter端实现M... 查看详情
flutterflutter混合开发(dart代码调试|flutter单独调试|混合模式下flutter调试)
...试Dart代码三、相关资源前言Flutter混合开发集成步骤:①在AndroidStudio中创建FlutterModule;②为Native应用添加FlutterModule依赖;③在Native应用(Android/iOS应用)中,调用FlutterModule模块;④编写FlutterModule中的D 查看详情
flutter(六)android与flutter混合开发(hybird)
参考技术A如果我们目前的项目是Android的,但是接下来我们希望部分页面可以使用Flutter进行开发,甚至我们希望在Native页面中嵌入FlutterUI组件,那么我们该如何实现呢?假设你现在Android项目的目录的结构是这样的这时候如果你... 查看详情
flutter混合开发实战
...个新的需求需要使用Flutter单独开一个模块集成到原有的android项目中下面分享一下如何集成现有的项目和如何继承以及碰到的问题1.首先第一步修改gradle因为Flutter当前仅支持为x86_64,armeabi-v7a和arm64-v8a构建预编(AOT)的库所以我... 查看详情
flutterflutter混合开发(安卓端向flutter传递数据|flutterfragment数据传递|flutteractivity数据传递)(代码片段)
...相关资源前言在上一篇博客【Flutter】Flutter混合开发(关联Android工程与Flutter工程|安卓页面中嵌入Flutter页面|安卓中启动Flutter页面)中,创建Android工程,并将两个工程进行关联,在Android的Activity界面中嵌入了FlutterFragment 查看详情
flutterflutter混合开发(关联android工程与flutter工程|安卓页面中嵌入flutter页面|安卓中启动flutter页面)(代码片段)
文章目录前言一、创建Android项目二、关联Android工程与FlutterModule工程1、配置FlutterModule工程2、配置build.gradle3、配置AndroidManifest.xml三、Activity中嵌入FlutterFragment页面四、Activity中启动FlutterActivity页面五、完整代码示例1、Android主界... 查看详情
混合开发架构|android工程集成reactnativeflutterreactjs(代码片段)
混合开发架构|Android工程集成ReactNative、Flutter、ReactJs架构设计说明创建安卓原生工程创建Flutter集成嵌入原生工程创建ReactNative解决RN报错问题集成嵌入原生工程RN集成后,启动报错底部导航栏架构设计原生仿招商银行首页原生... 查看详情
flutterflutter混合开发(简介|flutter混合开发集成步骤|创建fluttermodule)(代码片段)
文章目录一、Flutter混合开发简介二、Flutter混合开发集成步骤三、创建FlutterModule1、使用命令行创建FlutterModule项目(仅做参考)2、AndroidStudio中创建FlutterModule(推荐)3、FlutterModule项目文件结构四、相关资源一、Flutter混合开发简介开发... 查看详情