鸿蒙Flutter跨平台开发实践:融合创新与实战探索
本文探讨了华为鸿蒙系统与Flutter框架的融合开发实践。通过对比分析两种技术的优势,提出结合方案可兼顾开发效率与多端适配能力。文章详细介绍了环境配置步骤和项目创建方法,展示了融合项目的目录结构。核心代码部分呈现了鸿蒙Flutter应用的启动流程和特色页面实现,包括分布式任务流转等鸿蒙特性。这种技术融合为开发者提供了新的跨平台开发选择,在保持Flutter高效开发的同时,能够利用鸿蒙的分布式能力。
鸿蒙Flutter跨平台开发实践:融合创新与实战探索
一、技术融合背景与意义
在万物互联的时代背景下,华为鸿蒙系统与Google Flutter框架的相遇,为开发者带来了全新的可能性。鸿蒙作为新一代分布式操作系统,强调"一次开发,多端部署"的理念,而Flutter则以其卓越的跨平台UI渲染能力著称。本文将深入探讨两者的融合实践,并提供完整的代码示例。
1.1 技术优势对比
| 特性 | 鸿蒙原生开发 | Flutter跨平台开发 | 鸿蒙+Flutter融合 |
|---|---|---|---|
| 开发效率 | 中等 | 高 | 高 |
| 性能表现 | 优秀 | 优秀 | 良好 |
| 多端适配 | 优秀 | 良好 | 优秀 |
| 生态丰富度 | 成长中 | 成熟 | 互补 |
| 学习曲线 | 陡峭 | 平缓 | 中等 |
二、环境搭建与项目创建
2.1 开发环境配置
步骤一:安装必要工具
# 安装Flutter SDK
git clone https://github.com/flutter/flutter.git -b stable
export PATH="$PATH:`pwd`/flutter/bin"
# 安装鸿蒙开发工具
# 从华为开发者联盟下载DevEco Studio
# 安装鸿蒙Flutter桥接插件
flutter pub global activate harmony_flutter
步骤二:配置环境变量
# 在~/.bash_profile或~/.zshrc中添加
export HARMONY_SDK_PATH=/Users/username/HarmonyOS/Sdk
export FLUTTER_HARMONY=true
2.2 创建融合项目
# 使用专用模板创建项目
flutter create --template=harmony my_harmony_app
cd my_harmony_app
# 初始化鸿蒙模块
flutter harmony init
项目结构解析:
my_harmony_app/
├── lib/ # Flutter Dart代码
│ ├── main.dart # 应用入口
│ ├── harmony/ # 鸿蒙适配层
│ └── widgets/ # 自定义组件
├── harmony/ # 鸿蒙原生模块
│ ├── entry/ # 应用入口
│ ├── flutter_engine/ # Flutter引擎封装
│ └── ability/ # 鸿蒙Ability
├── android/ # Android支持
├── ios/ # iOS支持
└── pubspec.yaml # 依赖配置
三、核心代码实现
3.1 鸿蒙Flutter启动器
lib/main.dart - 应用主入口
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'harmony/harmony_channel.dart';
void main() {
// 初始化鸿蒙平台
WidgetsFlutterBinding.ensureInitialized();
// 设置鸿蒙平台UI特性
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
systemNavigationBarColor: Colors.white,
systemNavigationBarIconBrightness: Brightness.dark,
));
runApp(HarmonyFlutterApp());
}
class HarmonyFlutterApp extends StatelessWidget {
final HarmonyChannel _harmonyChannel = HarmonyChannel();
Widget build(BuildContext context) {
return MaterialApp(
title: '鸿蒙Flutter融合应用',
theme: _buildHarmonyTheme(),
home: HarmonyHomePage(channel: _harmonyChannel),
routes: {
'/distributed': (context) => DistributedPage(),
'/atomic': (context) => AtomicServicePage(),
},
);
}
ThemeData _buildHarmonyTheme() {
return ThemeData(
primaryColor: Color(0xFF007DFF), // 鸿蒙主题蓝
primaryColorLight: Color(0xFF4DA6FF),
primaryColorDark: Color(0xFF0052CC),
accentColor: Color(0xFFFF6A00), // 鸿蒙强调色
fontFamily: 'HarmonyOS Sans', // 鸿蒙字体
visualDensity: VisualDensity.adaptivePlatformDensity,
platform: TargetPlatform.android, // 暂时使用Android平台
appBarTheme: AppBarTheme(
elevation: 0,
centerTitle: true,
backgroundColor: Colors.white,
foregroundColor: Color(0xFF182431),
),
);
}
}
3.2 鸿蒙特色页面实现
lib/pages/harmony_home_page.dart
import 'package:flutter/material.dart';
import 'package:flutter_harmony/harmony_device.dart';
class HarmonyHomePage extends StatefulWidget {
final HarmonyChannel channel;
const HarmonyHomePage({Key? key, required this.channel}) : super(key: key);
_HarmonyHomePageState createState() => _HarmonyHomePageState();
}
class _HarmonyHomePageState extends State<HarmonyHomePage> {
List<HarmonyDevice> _connectedDevices = [];
bool _isDistributedMode = false;
void initState() {
super.initState();
_initHarmonyServices();
}
Future<void> _initHarmonyServices() async {
// 初始化鸿蒙服务
await widget.channel.initialize();
// 监听设备连接
widget.channel.deviceStream.listen((devices) {
setState(() {
_connectedDevices = devices;
});
});
// 检查分布式能力
final canDistribute = await widget.channel.checkDistributedCapability();
setState(() {
_isDistributedMode = canDistribute;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Row(
children: [
Icon(Icons.developer_board, color: Theme.of(context).primaryColor),
SizedBox(width: 8),
Text('鸿蒙Flutter实验室'),
],
),
actions: [
IconButton(
icon: Icon(Icons.devices),
onPressed: _showDevicePanel,
tooltip: '设备管理',
),
],
),
body: _buildContent(),
floatingActionButton: _buildHarmonyFAB(),
);
}
Widget _buildContent() {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// 鸿蒙特性卡片
_buildFeatureCard(
icon: Icons.share,
title: '分布式任务流转',
description: '跨设备无缝接续任务',
onTap: () => _startDistributedTask(),
enabled: _isDistributedMode,
),
_buildFeatureCard(
icon: Icons.apps,
title: '原子化服务',
description: '免安装,即点即用',
onTap: () => _launchAtomicService(),
),
_buildFeatureCard(
icon: Icons.settings_remote,
title: '超级终端',
description: '${_connectedDevices.length}个设备已连接',
onTap: _showSuperTerminal,
),
// 设备列表
if (_connectedDevices.isNotEmpty) ...[
Padding(
padding: EdgeInsets.all(16),
child: Text(
'已连接设备',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.grey[700],
),
),
),
Expanded(
child: ListView.builder(
itemCount: _connectedDevices.length,
itemBuilder: (context, index) {
return _buildDeviceItem(_connectedDevices[index]);
},
),
),
],
],
);
}
Widget _buildFeatureCard({
required IconData icon,
required String title,
required String description,
required VoidCallback onTap,
bool enabled = true,
}) {
return Card(
margin: EdgeInsets.all(8),
child: ListTile(
leading: Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: enabled
? Theme.of(context).primaryColor.withOpacity(0.1)
: Colors.grey[200],
borderRadius: BorderRadius.circular(8),
),
child: Icon(
icon,
color: enabled
? Theme.of(context).primaryColor
: Colors.grey,
),
),
title: Text(
title,
style: TextStyle(
fontWeight: FontWeight.w500,
color: enabled ? Colors.black : Colors.grey,
),
),
subtitle: Text(description),
trailing: enabled ? Icon(Icons.chevron_right) : null,
onTap: enabled ? onTap : null,
),
);
}
Widget _buildDeviceItem(HarmonyDevice device) {
return ListTile(
leading: Icon(
_getDeviceIcon(device.type),
color: Theme.of(context).primaryColor,
),
title: Text(device.name),
subtitle: Text('${device.type} · ${device.status}'),
trailing: Chip(
label: Text(device.distance < 10 ? '附近' : '远程'),
backgroundColor: device.distance < 10
? Colors.green[100]
: Colors.blue[100],
),
);
}
Widget _buildHarmonyFAB() {
return FloatingActionButton.extended(
onPressed: _showHarmonyMenu,
icon: Icon(Icons.handyman),
label: Text('鸿蒙工具'),
backgroundColor: Theme.of(context).primaryColor,
);
}
// 工具方法
IconData _getDeviceIcon(String type) {
switch (type) {
case 'phone': return Icons.phone_android;
case 'tablet': return Icons.tablet;
case 'tv': return Icons.tv;
case 'watch': return Icons.watch;
default: return Icons.device_unknown;
}
}
void _showDevicePanel() async {
final result = await showModalBottomSheet(
context: context,
builder: (context) => DeviceManagementPanel(
channel: widget.channel,
devices: _connectedDevices,
),
);
if (result != null) {
setState(() {
_connectedDevices = result;
});
}
}
void _startDistributedTask() {
// 实现分布式任务启动逻辑
}
void _launchAtomicService() {
// 启动原子化服务
}
void _showSuperTerminal() {
// 显示超级终端控制面板
}
void _showHarmonyMenu() {
// 显示鸿蒙工具菜单
}
}
3.3 鸿蒙原生桥接层
lib/harmony/harmony_channel.dart
import 'dart:async';
import 'package:flutter/services.dart';
class HarmonyDevice {
final String id;
final String name;
final String type;
final String status;
final int distance; // 距离(米)
HarmonyDevice({
required this.id,
required this.name,
required this.type,
required this.status,
required this.distance,
});
}
class HarmonyChannel {
static const MethodChannel _channel =
MethodChannel('com.example.harmony_flutter/bridge');
final StreamController<List<HarmonyDevice>> _deviceController =
StreamController.broadcast();
Stream<List<HarmonyDevice>> get deviceStream => _deviceController.stream;
Future<void> initialize() async {
// 设置方法调用处理器
_channel.setMethodCallHandler(_handleMethodCall);
// 初始化鸿蒙桥接
try {
await _channel.invokeMethod('initialize');
print('鸿蒙桥接初始化成功');
} on PlatformException catch (e) {
print('鸿蒙桥接初始化失败: ${e.message}');
}
}
Future<dynamic> _handleMethodCall(MethodCall call) async {
switch (call.method) {
case 'onDeviceListUpdated':
final devices = (call.arguments as List)
.map((item) => HarmonyDevice(
id: item['id'],
name: item['name'],
type: item['type'],
status: item['status'],
distance: item['distance'],
))
.toList();
_deviceController.add(devices);
break;
case 'onDistributedTaskResult':
// 处理分布式任务结果
break;
default:
throw PlatformException(
code: 'not_implemented',
message: '方法 ${call.method} 未实现',
);
}
}
Future<bool> checkDistributedCapability() async {
try {
final result = await _channel.invokeMethod('checkDistributedCapability');
return result == true;
} on PlatformException {
return false;
}
}
Future<void> startAtomicService(String serviceId) async {
await _channel.invokeMethod('startAtomicService', {
'serviceId': serviceId,
'timestamp': DateTime.now().millisecondsSinceEpoch,
});
}
Future<List<String>> getSupportedServices() async {
try {
final result = await _channel.invokeMethod('getSupportedServices');
return List<String>.from(result);
} on PlatformException {
return [];
}
}
Future<void> connectToDevice(String deviceId) async {
await _channel.invokeMethod('connectToDevice', {
'deviceId': deviceId,
'action': 'pair',
});
}
Future<void> disconnectDevice(String deviceId) async {
await _channel.invokeMethod('disconnectDevice', {
'deviceId': deviceId,
});
}
Future<Map<String, dynamic>> getDeviceCapabilities(String deviceId) async {
try {
final result = await _channel.invokeMethod('getDeviceCapabilities', {
'deviceId': deviceId,
});
return Map<String, dynamic>.from(result);
} on PlatformException {
return {};
}
}
Future<void> startDistributedTask(
String taskType,
Map<String, dynamic> data,
) async {
await _channel.invokeMethod('startDistributedTask', {
'taskType': taskType,
'data': data,
'uuid': _generateUuid(),
});
}
String _generateUuid() {
return '${DateTime.now().millisecondsSinceEpoch}-${UniqueKey().toString()}';
}
void dispose() {
_deviceController.close();
}
}
四、鸿蒙原生适配代码
4.1 HarmonyOS侧Flutter引擎封装
harmony/entry/src/main/ets/MainAbility/MainAbility.ts
import Ability from '@ohos.application.Ability';
import FlutterEngine from '@ohos.flutter.engine';
export default class MainAbility extends Ability {
private flutterEngine: FlutterEngine | null = null;
private deviceList: Array<DeviceInfo> = [];
onCreate(want, launchParam) {
console.log('MainAbility onCreate');
this.initFlutterEngine();
this.startDeviceDiscovery();
}
private initFlutterEngine(): void {
this.flutterEngine = new FlutterEngine(this.context);
// 配置Flutter引擎参数
this.flutterEngine.setInitialRoute('/');
this.flutterEngine.setDartEntrypointFunctionName('main');
// 设置平台通道
this.setupMethodChannel();
// 启动Flutter引擎
this.flutterEngine.run();
}
private setupMethodChannel(): void {
if (!this.flutterEngine) return;
const channel = this.flutterEngine.createMethodChannel('com.example.harmony_flutter/bridge');
channel.setMethodCallHandler(async (call) => {
console.log(`收到Flutter调用: ${call.method}`);
switch (call.method) {
case 'initialize':
return this.handleInitialize(call);
case 'checkDistributedCapability':
return this.checkDistributedCapability();
case 'startAtomicService':
return this.startAtomicService(call.arguments);
case 'getSupportedServices':
return this.getSupportedServices();
case 'connectToDevice':
return this.connectToDevice(call.arguments);
case 'disconnectDevice':
return this.disconnectDevice(call.arguments);
case 'getDeviceCapabilities':
return this.getDeviceCapabilities(call.arguments);
case 'startDistributedTask':
return this.startDistributedTask(call.arguments);
default:
console.warn(`未知方法: ${call.method}`);
throw new Error(`Method ${call.method} not implemented`);
}
});
}
private async handleInitialize(call: any): Promise<void> {
// 初始化设备发现服务
await this.initDeviceManager();
return Promise.resolve();
}
private async initDeviceManager(): Promise<void> {
try {
// 鸿蒙设备管理API调用
const deviceManager = await this.context.getDeviceManager();
deviceManager.on('deviceFound', (data) => {
this.onDeviceFound(data);
});
deviceManager.startDiscovery();
} catch (error) {
console.error('设备管理器初始化失败:', error);
}
}
private onDeviceFound(deviceInfo: any): void {
const device: DeviceInfo = {
id: deviceInfo.deviceId,
name: deviceInfo.deviceName,
type: deviceInfo.deviceType,
status: 'available',
distance: deviceInfo.rssi ? this.calculateDistance(deviceInfo.rssi) : 0,
};
// 避免重复添加
if (!this.deviceList.some(d => d.id === device.id)) {
this.deviceList.push(device);
this.notifyDeviceListUpdate();
}
}
private calculateDistance(rssi: number): number {
// 简单的距离估算公式
const txPower = -59; // 1米处的RSSI值
if (rssi === 0) return -1;
const ratio = rssi * 1.0 / txPower;
if (ratio < 1.0) {
return Math.pow(ratio, 10);
} else {
return (0.89976) * Math.pow(ratio, 7.7095) + 0.111;
}
}
private notifyDeviceListUpdate(): void {
if (this.flutterEngine) {
const channel = this.flutterEngine.getMethodChannel('com.example.harmony_flutter/bridge');
channel.invokeMethod('onDeviceListUpdated', this.deviceList);
}
}
private checkDistributedCapability(): boolean {
// 检查设备是否支持分布式能力
try {
const feature = this.context.getDistributedAbility();
return feature.isSupported();
} catch {
return false;
}
}
private async startAtomicService(args: any): Promise<void> {
const { serviceId, timestamp } = args;
const want = {
bundleName: 'com.example.atomic',
abilityName: serviceId,
parameters: {
launchTime: timestamp,
source: 'flutter_app'
}
};
await this.context.startAbility(want);
}
private getSupportedServices(): string[] {
// 返回支持的原子化服务列表
return [
'com.example.weather',
'com.example.calculator',
'com.example.notes',
'com.example.quick_settings'
];
}
private connectToDevice(args: any): Promise<void> {
const { deviceId, action } = args;
console.log(`连接设备: ${deviceId}, 操作: ${action}`);
// 实现设备连接逻辑
return Promise.resolve();
}
private disconnectDevice(args: any): Promise<void> {
const { deviceId } = args;
// 从列表中移除设备
this.deviceList = this.deviceList.filter(device => device.id !== deviceId);
this.notifyDeviceListUpdate();
return Promise.resolve();
}
private getDeviceCapabilities(args: any): any {
const { deviceId } = args;
// 查询设备能力
const device = this.deviceList.find(d => d.id === deviceId);
if (!device) {
return {};
}
return {
deviceId: device.id,
capabilities: {
screenSharing: true,
fileTransfer: true,
remoteControl: device.type === 'tv',
audioSync: true,
},
maxConnections: 5,
protocolVersion: '2.0'
};
}
private startDistributedTask(args: any): Promise<string> {
const { taskType, data, uuid } = args;
console.log(`启动分布式任务: ${taskType}, UUID: ${uuid}`);
// 实现分布式任务启动逻辑
return Promise.resolve(`task_${uuid}`);
}
onDestroy() {
console.log('MainAbility onDestroy');
if (this.flutterEngine) {
this.flutterEngine.destroy();
}
}
onWindowStageCreate(windowStage) {
console.log('MainAbility onWindowStageCreate');
windowStage.loadContent('pages/Index', (err, data) => {
if (err.code) {
console.error('加载页面失败:', err);
return;
}
console.log('页面加载成功');
});
}
}
interface DeviceInfo {
id: string;
name: string;
type: string;
status: string;
distance: number;
}
五、构建与调试技巧
5.1 构建脚本配置
build_harmony.sh
#!/bin/bash
# 鸿蒙Flutter构建脚本
echo "开始构建鸿蒙Flutter应用..."
# 清理构建缓存
flutter clean
# 获取Flutter依赖
flutter pub get
# 生成Dart代码
dart run build_runner build --delete-conflicting-outputs
# 构建HarmonyOS应用
echo "构建HarmonyOS模块..."
cd harmony
# 编译HAP包
gradle buildHap
if [ $? -eq 0 ]; then
echo "✅ HarmonyOS应用构建成功!"
echo "输出文件: harmony/entry/build/outputs/hap/debug/entry-debug.hap"
else
echo "❌ HarmonyOS应用构建失败"
exit 1
fi
# 返回项目根目录
cd ..
# 可选:同时构建Android版本
echo "构建Android版本..."
flutter build apk --release
echo "🎉 所有构建完成!"
5.2 调试配置
.vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "HarmonyOS调试",
"type": "dart",
"request": "launch",
"program": "lib/main.dart",
"args": [
"--harmony",
"--enable-profiling"
],
"flutterMode": "debug",
"tooltip": "在HarmonyOS设备上调试"
},
{
"name": "HarmonyOS性能分析",
"type": "dart",
"request": "launch",
"program": "lib/main.dart",
"args": [
"--harmony",
"--profile"
],
"flutterMode": "profile"
},
{
"name": "多平台测试",
"type": "dart",
"request": "launch",
"program": "lib/main.dart",
"args": [
"--harmony",
"--android",
"--verbose"
],
"flutterMode": "debug"
}
]
}
六、性能优化建议
6.1 渲染优化技巧
// 使用const优化性能
class OptimizedHarmonyWidget extends StatelessWidget {
const OptimizedHarmonyWidget({
Key? key,
required this.title,
required this.harmonyData,
}) : super(key: key);
final String title;
final HarmonyData harmonyData;
Widget build(BuildContext context) {
return ConstrainedBox(
constraints: const BoxConstraints(
minHeight: 50,
maxHeight: 200,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 使用缓存图标
const HarmonyIcon(
type: HarmonyIconType.device,
size: 24,
),
const SizedBox(height: 8),
// 选择性重建
Selector<HarmonyModel, String>(
selector: (_, model) => model.deviceName,
builder: (_, deviceName, __) {
return Text(
deviceName,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
);
},
),
],
),
);
}
}
// 使用AnimatedBuilder优化动画性能
class HarmonyDeviceTile extends StatefulWidget {
_HarmonyDeviceTileState createState() => _HarmonyDeviceTileState();
}
class _HarmonyDeviceTileState extends State<HarmonyDeviceTile>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
void initState() {
super.initState();
_animationController = AnimationController(
duration: const Duration(milliseconds: 300),
vsync: this,
);
}
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animationController,
builder: (context, child) {
return Transform.scale(
scale: 1.0 + _animationController.value * 0.1,
child: child,
);
},
child: _buildContent(),
);
}
Widget _buildContent() {
return ListTile(
// ... 列表内容
);
}
}
6.2 内存管理优化
// 使用Provider管理状态,避免不必要的重建
class HarmonyProvider extends ChangeNotifier {
List<HarmonyDevice> _devices = [];
bool _isLoading = false;
List<HarmonyDevice> get devices => _devices;
bool get isLoading => _isLoading;
Future<void> loadDevices() async {
if (_isLoading) return;
_isLoading = true;
notifyListeners();
try {
// 异步加载设备列表
final newDevices = await HarmonyApi.getDevices();
_devices = newDevices;
} catch (e) {
print('加载设备失败: $e');
} finally {
_isLoading = false;
notifyListeners();
}
}
// 使用缓存策略
static final Map<String, HarmonyDevice> _deviceCache = {};
Future<HarmonyDevice> getDeviceDetails(String deviceId) async {
// 检查缓存
if (_deviceCache.containsKey(deviceId)) {
return _deviceCache[deviceId]!;
}
// 从API获取
final device = await HarmonyApi.getDeviceDetails(deviceId);
// 存入缓存
_deviceCache[deviceId] = device;
return device;
}
// 清理缓存
void clearCache() {
_deviceCache.clear();
notifyListeners();
}
}
七、总结与展望
通过本文的实践探索,我们成功实现了Flutter应用在鸿蒙系统上的运行,并充分利用了鸿蒙的分布式能力和原子化服务特性。这种融合方案具有以下优势:
7.1 技术优势
- 开发效率提升:利用Flutter的热重载和丰富的UI组件
- 性能表现良好:通过原生桥接实现接近原生应用的性能
- 多端统一:一套代码支持鸿蒙、Android、iOS等多个平台
- 生态互补:结合Flutter的成熟生态和鸿蒙的特色功能
7.2 挑战与应对
- API兼容性:需要维护鸿蒙专用的桥接层
- 调试复杂度:需要同时掌握Flutter和鸿蒙开发工具
- 版本适配:关注鸿蒙系统和Flutter SDK的版本更新
7.3 未来展望
随着鸿蒙生态的不断完善和Flutter对HarmonyOS的官方支持,我们有理由相信:
1.跨平台开发体验将持续优化
Flutter框架将深度适配HarmonyOS的核心特性,如分布式能力、原子化服务等。开发者可以更便捷地调用系统级API,实现一次开发多端部署。例如,通过Flutter插件机制快速集成鸿蒙的分布式数据管理能力。
2.开发者生态将加速繁荣
官方支持将吸引更多Flutter开发者加入鸿蒙生态。预计未来会出现:
.专门的HarmonyOS-Flutter组件库
更完善的开发工具链(如DevEco Studio插件)
丰富的学习资源和社区支持
3.性能表现将显著提升
通过底层引擎优化(如Skia渲染引擎与鸿蒙图形系统的深度整合),Flutter应用在HarmonyOS上的运行效率有望达到原生应用水平。特别是在动画渲染、列表滚动等关键场景会有明显改善。
4.应用场景将更加多元化
结合鸿蒙的"1+8+N"全场景战略,Flutter开发的智能终端应用将覆盖:
手机、平板等移动设备
智能家居、车载系统等IoT场景
智慧办公、运动健康等垂直领域
5.商业化前景广阔
据华为2023年开发者大会数据,鸿蒙生态设备已突破7亿台。Flutter的加入将为开发者带来更广阔的商业机会,特别是在全球化应用分发和跨设备服务联动方面。
更多推荐



所有评论(0)