作者链接哇是林啊标签:#harmonyos #flutter #状态管理 #分布式数据 #provider

在上一篇文章中,我们完成了鸿蒙与 Flutter 的基础集成和原生通信。本文将聚焦更复杂的实战场景:使用 Provider 进行 Flutter 状态管理,并结合鸿蒙分布式数据管理(DataShare)实现多设备数据同步。通过完整的代码案例,讲解从数据建模、状态管理到分布式同步的全流程,助力开发者构建高性能、多设备适配的鸿蒙 - Flutter 应用。

一、核心技术选型说明

  • 状态管理:Provider 6.0+(轻量、易集成,适合中小型应用的状态共享)
  • 分布式数据:鸿蒙 DataShare(基于鸿蒙分布式能力,支持多设备数据实时同步)
  • 网络 / 存储:shared_preferences(Flutter 端本地存储)+ 鸿蒙 DataShare SDK
  • 开发环境:延续上一篇的配置(DevEco Studio 4.0+ + Flutter 3.13+)

二、项目基础架构搭建

2.1 依赖添加

flutter_module/pubspec.yaml中添加 Provider 和 shared_preferences 依赖:

yaml

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.1.1
  shared_preferences: ^2.2.2

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^2.0.0

执行flutter pub get安装依赖。

2.2 数据模型定义

创建flutter_module/lib/model/user_model.dart,定义用户数据模型(用于状态管理和分布式同步):

dart

class UserModel {
  final String userId;
  String userName;
  int age;
  String deviceId; // 记录数据所属设备ID

  UserModel({
    required this.userId,
    required this.userName,
    required this.age,
    required this.deviceId,
  });

  // 转JSON(用于与鸿蒙DataShare通信)
  Map<String, dynamic> toJson() => {
        'userId': userId,
        'userName': userName,
        'age': age,
        'deviceId': deviceId,
      };

  // 从JSON构建对象
  static UserModel fromJson(Map<String, dynamic> json) => UserModel(
        userId: json['userId'],
        userName: json['userName'],
        age: json['age'],
        deviceId: json['deviceId'],
      );
}

三、基于 Provider 的状态管理实现

3.1 创建状态管理类

创建flutter_module/lib/provider/user_provider.dart,封装用户数据的状态管理逻辑:

dart

import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/services.dart';
import '../model/user_model.dart';

class UserProvider extends ChangeNotifier {
  UserModel? _currentUser;
  static const MethodChannel _dataShareChannel = MethodChannel('com.example.harmony_flutter/datashare');

  UserModel? get currentUser => _currentUser;

  // 初始化:从本地存储或分布式数据加载用户信息
  Future<void> initUser() async {
    // 1. 先从本地存储加载
    final prefs = await SharedPreferences.getInstance();
    final userJson = prefs.getString('current_user');
    
    if (userJson != null) {
      _currentUser = UserModel.fromJson({'userId': '', 'userName': '', 'age': 0, 'deviceId': ''}..addAll(await _dataShareChannel.invokeMethod('getUser')));
      notifyListeners();
      return;
    }

    // 2. 本地无数据时,从鸿蒙分布式数据加载
    try {
      final result = await _dataShareChannel.invokeMethod('getUser');
      if (result != null) {
        _currentUser = UserModel.fromJson(result);
        // 同步到本地存储
        await prefs.setString('current_user', result.toString());
      }
    } catch (e) {
      debugPrint('从分布式数据加载失败:$e');
    }
    notifyListeners();
  }

  // 更新用户信息(同步到本地和分布式数据)
  Future<void> updateUser({required String userName, required int age}) async {
    if (_currentUser == null) return;

    // 更新内存状态
    _currentUser!.userName = userName;
    _currentUser!.age = age;
    notifyListeners();

    // 同步到本地存储
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString('current_user', _currentUser!.toJson().toString());

    // 同步到鸿蒙分布式数据
    try {
      await _dataShareChannel.invokeMethod('updateUser', _currentUser!.toJson());
    } catch (e) {
      debugPrint('同步到分布式数据失败:$e');
    }
  }
}

3.2 在 Flutter 应用中注入 Provider

修改flutter_module/lib/main.dart,通过ChangeNotifierProvider注入状态管理:

dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'provider/user_provider.dart';
import 'pages/user_info_page.dart';

void main() => runApp(
      // 注入Provider
      ChangeNotifierProvider(
        create: (context) => UserProvider()..initUser(),
        child: const MyApp(),
      ),
    );

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '鸿蒙-Flutter分布式Demo',
      theme: ThemeData(primarySwatch: Colors.green),
      home: const UserInfoPage(),
    );
  }
}

3.3 编写 Flutter 页面(状态共享与更新)

创建flutter_module/lib/pages/user_info_page.dart,实现用户信息展示和编辑功能:

dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../provider/user_provider.dart';

class UserInfoPage extends StatefulWidget {
  const UserInfoPage({super.key});

  @override
  State<UserInfoPage> createState() => _UserInfoPageState();
}

class _UserInfoPageState extends State<UserInfoPage> {
  final TextEditingController _nameController = TextEditingController();
  final TextEditingController _ageController = TextEditingController();

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // 从Provider获取用户信息并填充到输入框
    final user = Provider.of<UserProvider>(context).currentUser;
    if (user != null) {
      _nameController.text = user.userName;
      _ageController.text = user.age.toString();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('用户信息管理(分布式同步)')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Consumer<UserProvider>(
          builder: (context, provider, child) {
            final user = provider.currentUser;
            if (user == null) {
              return const Center(child: CircularProgressIndicator());
            }
            return Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                // 显示设备ID(标识数据来源设备)
                Text('当前设备ID:${user.deviceId}', style: const TextStyle(color: Colors.grey)),
                const SizedBox(height: 20),
                TextField(
                  controller: _nameController,
                  decoration: const InputDecoration(labelText: '用户名'),
                ),
                const SizedBox(height: 16),
                TextField(
                  controller: _ageController,
                  decoration: const InputDecoration(labelText: '年龄'),
                  keyboardType: TextInputType.number,
                ),
                const SizedBox(height: 30),
                Center(
                  child: ElevatedButton(
                    onPressed: () {
                      final name = _nameController.text.trim();
                      final age = int.tryParse(_ageController.text.trim()) ?? 0;
                      if (name.isNotEmpty) {
                        provider.updateUser(userName: name, age: age);
                        ScaffoldMessenger.of(context).showSnackBar(
                          const SnackBar(content: Text('信息更新成功,已同步到所有设备')),
                        );
                      }
                    },
                    child: const Text('更新信息(分布式同步)'),
                  ),
                ),
              ],
            );
          },
        ),
      ),
    );
  }

  @override
  void dispose() {
    _nameController.dispose();
    _ageController.dispose();
    super.dispose();
  }
}

四、鸿蒙分布式数据同步(DataShare)实现

4.1 鸿蒙端 DataShare 服务配置

(1)创建 DataShare 能力

在鸿蒙项目中创建entry/src/main/java/com/example/harmony_flutter_demo/datashare目录,创建UserDataShare.java

java

运行

import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.data.dataability.DataAbilityHelper;
import ohos.data.dataability.DataAbilityRemoteException;
import ohos.data.rdb.RdbOpenCallback;
import ohos.data.rdb.RdbStore;
import ohos.data.rdb.StoreConfig;
import ohos.data.resultset.ResultSet;
import ohos.data.valueset.ValueSet;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.system.DeviceInfo;

import java.util.HashMap;
import java.util.Map;

public class UserDataShare extends Ability {
    private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00100, "UserDataShare");
    private static final String DB_NAME = "user_db.db";
    private static final int DB_VERSION = 1;
    private static final String TABLE_NAME = "user";
    private RdbStore rdbStore;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        // 初始化数据库
        initRdbStore();
    }

    // 初始化RDB数据库
    private void initRdbStore() {
        StoreConfig config = StoreConfig.newDefaultConfig(DB_NAME);
        RdbOpenCallback callback = new RdbOpenCallback() {
            @Override
            public void onCreate(RdbStore store) {
                // 创建用户表
                store.executeSql("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
                        "userId TEXT PRIMARY KEY, " +
                        "userName TEXT, " +
                        "age INTEGER, " +
                        "deviceId TEXT)");
                // 初始化默认用户数据
                String deviceId = DeviceInfo.getDeviceId();
                ValueSet valueSet = new ValueSet();
                valueSet.putString("userId", "default_user");
                valueSet.putString("userName", "默认用户");
                valueSet.putInteger("age", 20);
                valueSet.putString("deviceId", deviceId);
                store.insert(TABLE_NAME, valueSet);
            }

            @Override
            public void onUpgrade(RdbStore store, int oldVersion, int newVersion) {}
        };
        rdbStore = openRdbStore(config, DB_VERSION, callback, null);
    }

    // 获取用户信息(供Flutter调用)
    public Map<String, Object> getUserInfo() {
        Map<String, Object> userMap = new HashMap<>();
        try {
            ResultSet resultSet = rdbStore.query(TABLE_NAME, null, null, null, null, null, null);
            if (resultSet.moveToFirst()) {
                userMap.put("userId", resultSet.getString(resultSet.getColumnIndexForName("userId")));
                userMap.put("userName", resultSet.getString(resultSet.getColumnIndexForName("userName")));
                userMap.put("age", resultSet.getInt(resultSet.getColumnIndexForName("age")));
                userMap.put("deviceId", resultSet.getString(resultSet.getColumnIndexForName("deviceId")));
            }
            resultSet.close();
        } catch (Exception e) {
            HiLog.error(LABEL, "获取用户信息失败:%s", e.getMessage());
        }
        return userMap;
    }

    // 更新用户信息(供Flutter调用)
    public boolean updateUserInfo(Map<String, Object> userMap) {
        try {
            ValueSet valueSet = new ValueSet();
            valueSet.putString("userName", (String) userMap.get("userName"));
            valueSet.putInteger("age", (Integer) userMap.get("age"));
            valueSet.putString("deviceId", DeviceInfo.getDeviceId());
            // 条件:更新默认用户
            String whereClause = "userId = ?";
            String[] whereArgs = {"default_user"};
            return rdbStore.update(TABLE_NAME, valueSet, whereClause, whereArgs) > 0;
        } catch (Exception e) {
            HiLog.error(LABEL, "更新用户信息失败:%s", e.getMessage());
            return false;
        }
    }
}
(2)注册 DataShare 服务

entry/src/main/module.json5中注册 DataShare 能力:

json

{
  "module": {
    "abilities": [
      {
        "name": "com.example.harmony_flutter_demo.datashare.UserDataShare",
        "type": "data",
        "uri": "dataability://com.example.harmony_flutter_demo.UserDataShare",
        "skills": [
          {
            "entities": ["ohos.utils.data.DataAbility"],
            "actions": ["ohos.want.action.GET_DATA", "ohos.want.action.SET_DATA"]
          }
        ]
      }
    ]
  }
}

4.2 扩展 MethodChannel 支持分布式数据通信

修改鸿蒙端的FlutterMethodCallHandler.java,添加 DataShare 相关方法处理:

java

运行

import com.example.harmony_flutter_demo.datashare.UserDataShare;
import java.util.Map;

public class FlutterMethodCallHandler implements MethodChannel.MethodCallHandler {
    private final Ability ability;
    private UserDataShare userDataShare;

    public FlutterMethodCallHandler(Ability ability) {
        this.ability = ability;
        // 初始化DataShare
        this.userDataShare = new UserDataShare();
        this.userDataShare.onStart(null);
    }

    @Override
    public void onMethodCall(MethodCall call, MethodChannel.Result result) {
        switch (call.method) {
            case "getDeviceInfo":
                // 上一篇的设备信息获取逻辑
                Map<String, String> deviceInfo = new HashMap<>();
                deviceInfo.put("deviceName", DeviceInfo.getDeviceName());
                deviceInfo.put("deviceModel", DeviceInfo.getDeviceModel());
                result.success(deviceInfo);
                break;
            case "getUser":
                // 获取分布式用户信息
                result.success(userDataShare.getUserInfo());
                break;
            case "updateUser":
                // 更新分布式用户信息
                Map<String, Object> userMap = (Map<String, Object>) call.arguments;
                boolean success = userDataShare.updateUserInfo(userMap);
                result.success(success);
                break;
            default:
                result.notImplemented();
                break;
        }
    }
}

五、功能测试与验证

5.1 测试步骤

  1. 启动两台鸿蒙设备(或模拟器),确保已登录同一华为账号并开启分布式能力
  2. 在两台设备上分别运行应用,初始状态会加载默认用户信息
  3. 在其中一台设备上修改用户名和年龄,点击 "更新信息" 按钮
  4. 切换到另一台设备,刷新页面(或重新进入应用),可看到信息已同步更新

5.2 关键验证点

  • 本地存储同步:修改后重启应用,信息不会丢失(shared_preferences 生效)
  • 分布式同步:多设备登录同一账号时,数据实时同步(DataShare 生效)
  • 状态管理:修改信息后,页面无需手动刷新即可更新(Provider 生效)

总结

本文通过 Provider 实现了 Flutter 端的状态管理,结合鸿蒙 DataShare 能力完成了多设备数据同步,构建了一个具备分布式特性的跨平台应用。核心亮点在于:

  1. 状态管理与分布式同步解耦:Provider 负责本地状态管理,鸿蒙 DataShare 负责跨设备同步,架构清晰
  2. 数据一致性保障:本地存储与分布式存储双向同步,确保离线场景下的数据可用性
  3. 原生能力深度集成:Flutter 通过 MethodChannel 无缝调用鸿蒙分布式 API,充分发挥鸿蒙生态优势

后续可扩展的方向:添加数据同步状态监听(如同步中、同步失败提示)、支持多用户数据管理、集成鸿蒙分布式文件服务实现文件同步等。如果需要进一步深入某个技术点,欢迎在评论区留言交流!

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐