1. 项目背景与核心需求
在移动应用开发领域,收藏夹功能几乎是所有内容型应用的标配功能模块。特别是在电商类应用中,用户收藏商品的行为数据直接反映了用户的消费偏好和潜在购买意向。传统收藏夹实现往往只停留在简单的数据存储层面,缺乏对用户行为的深度分析和个性化展示。
这次我们要实现的家具购买记录App收藏夹模块,需要突破以下几个技术难点:
- 跨平台兼容性:基于Flutter for OpenHarmony框架,确保在鸿蒙生态和Android/iOS平台表现一致
- 数据可视化:不仅要存储收藏记录,还要展示用户的收藏趋势和偏好
- 智能推荐:基于收藏行为生成个性化家具推荐
2. 技术架构设计
2.1 整体架构方案
采用分层架构设计,从上到下分为:
- 表现层:Flutter Widget构建的UI界面
- 业务逻辑层:Dart实现的收藏夹核心逻辑
- 数据层:包括本地存储和网络请求
- 原生适配层:OpenHarmony平台特定功能封装
dart复制// 架构示意图
class FavoritesArchitecture {
final UI = [
'收藏列表',
'分类视图',
'详情页'
];
final BusinessLogic = [
'收藏管理',
'智能推荐',
'数据分析'
];
final Data = [
'本地存储',
'网络请求',
'缓存管理'
];
final Native = [
'鸿蒙API适配',
'性能优化',
'硬件加速'
];
}
2.2 关键技术选型
2.2.1 状态管理方案
对比了Provider、Riverpod和BLoC后,最终选择Riverpod,原因包括:
- 更好的类型安全支持
- 更简洁的依赖注入方式
- 与Flutter 3.x的更好兼容性
- 更灵活的作用域控制
2.2.2 本地存储方案
采用Hive+ObjectBox组合方案:
- Hive:负责简单键值对存储(用户配置、临时数据)
- ObjectBox:负责复杂对象存储(收藏记录、用户行为)
注意:OpenHarmony需要额外配置存储权限和路径适配
3. 核心功能实现
3.1 收藏数据模型设计
dart复制@HiveType(typeId: 1)
class FurnitureItem {
@HiveField(0)
final String id;
@HiveField(1)
final String name;
@HiveField(2)
final String category;
@HiveField(3)
final double price;
@HiveField(4)
final List<String> imageUrls;
@HiveField(5)
final DateTime addedTime;
// 其他业务字段...
}
@HiveType(typeId: 2)
class FavoritesCollection {
@HiveField(0)
final String userId;
@HiveField(1)
final List<FurnitureItem> items;
@HiveField(2)
final Map<String, int> categoryCount;
// 自定义排序方法
void sortBy(SortType type) {
// 实现按价格、时间等排序逻辑
}
}
3.2 收藏交互实现
3.2.1 收藏/取消收藏逻辑
dart复制class FavoritesService {
final Ref ref;
Future<void> toggleFavorite(FurnitureItem item) async {
final favorites = await _loadFavorites();
final exists = favorites.items.any((i) => i.id == item.id);
if (exists) {
favorites.items.removeWhere((i) => i.id == item.id);
} else {
favorites.items.add(item);
}
await _updateCategoryStats(favorites);
await _saveFavorites(favorites);
ref.read(favoritesProvider.notifier).update(favorites);
}
// 其他辅助方法...
}
3.2.2 收藏状态同步
使用Riverpod的StateNotifier实现跨组件状态同步:
dart复制final favoritesProvider = StateNotifierProvider<FavoritesNotifier, FavoritesCollection>((ref) {
return FavoritesNotifier();
});
class FavoritesNotifier extends StateNotifier<FavoritesCollection> {
FavoritesNotifier() : super(FavoritesCollection.empty());
void update(FavoritesCollection newState) {
state = newState;
}
// 其他业务方法...
}
3.3 收藏列表展示
3.3.1 基础列表实现
dart复制class FavoritesListView extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final favorites = ref.watch(favoritesProvider);
return ListView.builder(
itemCount: favorites.items.length,
itemBuilder: (context, index) {
final item = favorites.items[index];
return FurnitureItemCard(
item: item,
onFavoriteToggled: () => ref.read(favoritesServiceProvider).toggleFavorite(item),
);
},
);
}
}
3.3.2 高级布局模式
实现多种视图切换功能:
dart复制enum ViewMode { list, grid, gallery }
class ViewModeSwitcher extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final mode = ref.watch(viewModeProvider);
return LayoutBuilder(
builder: (context, constraints) {
switch (mode) {
case ViewMode.list:
return _buildListLayout(ref);
case ViewMode.grid:
return _buildGridLayout(ref, constraints);
case ViewMode.gallery:
return _buildGalleryLayout(ref);
}
},
);
}
// 各种布局的具体实现...
}
4. 高级功能实现
4.1 智能分类与筛选
dart复制class CategoryFilter extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final favorites = ref.watch(favoritesProvider);
final activeCategory = ref.watch(categoryFilterProvider);
return Wrap(
spacing: 8,
children: [
FilterChip(
label: Text('全部'),
selected: activeCategory == null,
onSelected: (_) => ref.read(categoryFilterProvider.notifier).clear(),
),
...favorites.categoryCount.keys.map((category) {
return FilterChip(
label: Text('$category (${favorites.categoryCount[category]})'),
selected: activeCategory == category,
onSelected: (_) => ref.read(categoryFilterProvider.notifier).set(category),
);
}),
],
);
}
}
4.2 收藏数据分析
实现收藏趋势图表:
dart复制class FavoritesChart extends StatelessWidget {
final Map<DateTime, int> historyData;
@override
Widget build(BuildContext context) {
return LineChart(
LineChartData(
lineBarsData: [
LineChartBarData(
spots: historyData.entries.map((e) {
return FlSpot(e.key.millisecondsSinceEpoch.toDouble(), e.value.toDouble());
}).toList(),
),
],
// 其他图表配置...
),
);
}
}
4.3 多设备同步
基于OpenHarmony分布式能力实现:
dart复制class DistributedSync {
final DistributedDataManager manager;
Future<void> syncFavorites() async {
final favorites = await _loadLocalFavorites();
try {
await manager.sendData('favorites_update', favorites.toJson());
} catch (e) {
// 错误处理逻辑
}
}
void setupListener() {
manager.registerDataListener((deviceId, data) {
if (data['type'] == 'favorites_update') {
_handleRemoteUpdate(data['payload']);
}
});
}
}
5. 性能优化实践
5.1 列表渲染优化
dart复制class OptimizedFavoritesList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView.custom(
childrenDelegate: SliverChildBuilderDelegate(
(context, index) {
final item = _getItem(index);
return OptimizedCacheItem(item: item);
},
childCount: _itemCount,
findChildIndexCallback: (key) {
// 实现高效的索引查找逻辑
},
),
);
}
}
5.2 图片加载优化
dart复制class FurnitureImage extends StatelessWidget {
final String url;
@override
Widget build(BuildContext context) {
return OctoImage(
image: CachedNetworkImageProvider(url),
placeholderBuilder: (context) => ShimmerPlaceholder(),
errorBuilder: (context, error, stackTrace) => ErrorPlaceholder(),
fadeInDuration: const Duration(milliseconds: 300),
fit: BoxFit.cover,
);
}
}
5.3 数据库查询优化
dart复制class OptimizedFavoritesQuery {
final ObjectBox store;
Future<List<FurnitureItem>> queryByCategory(String category) async {
final query = store.box<FurnitureItem>()
.query(FurnitureItem_.category.equals(category))
.build();
// 使用延迟加载和分页
final items = query
.find(offset: 0, limit: 20)
.toList();
query.close();
return items;
}
}
6. 测试与调试
6.1 单元测试示例
dart复制void main() {
test('toggle favorite should update state', () async {
final container = ProviderContainer();
final service = container.read(favoritesServiceProvider);
final mockItem = FurnitureItem.testInstance();
// 初始状态验证
expect(container.read(favoritesProvider).items, isEmpty);
// 添加收藏
await service.toggleFavorite(mockItem);
expect(container.read(favoritesProvider).items, hasLength(1));
// 取消收藏
await service.toggleFavorite(mockItem);
expect(container.read(favoritesProvider).items, isEmpty);
});
}
6.2 集成测试要点
dart复制void main() {
integrationTest('full favorites flow', (tester) async {
// 初始化应用
await tester.pumpWidget(MyApp());
// 浏览到商品详情页
await tester.tap(find.text('沙发'));
await tester.pumpAndSettle();
// 点击收藏按钮
await tester.tap(find.byIcon(Icons.favorite_border));
await tester.pump();
// 验证收藏状态变化
expect(find.byIcon(Icons.favorite), findsOneWidget);
// 导航到收藏夹页面
await tester.tap(find.byKey(Key('favorites_tab')));
await tester.pumpAndSettle();
// 验证收藏项显示
expect(find.text('沙发'), findsOneWidget);
});
}
7. 项目部署与发布
7.1 OpenHarmony适配要点
在config.json中添加必要权限:
json复制{
"module": {
"reqPermissions": [
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC",
"reason": "多设备收藏夹同步"
},
{
"name": "ohos.permission.READ_USER_STORAGE",
"reason": "读取本地收藏数据"
},
{
"name": "ohos.permission.WRITE_USER_STORAGE",
"reason": "保存收藏数据"
}
]
}
}
7.2 多平台构建配置
pubspec.yaml关键配置:
yaml复制dependencies:
flutter:
sdk: flutter
hive: ^2.2.3
objectbox: ^1.7.0
flutter_riverpod: ^2.3.6
cached_network_image: ^3.2.3
ohos_distributed_data: ^0.0.1
flutter:
assets:
- assets/images/
- assets/database/
# OpenHarmony特定配置
ohos:
minSdkVersion: 8
targetSdkVersion: 9
compileSdkVersion: 9
8. 经验总结与进阶建议
在实际开发过程中,有几个关键点值得特别注意:
-
状态管理粒度:收藏夹的状态变化会影响UI的多个部分,建议将状态分为三个层级:
- 全局状态:用户收藏集合
- 页面状态:当前筛选条件
- 组件状态:单个收藏项的交互状态
-
性能取舍:在实现收藏夹的即时同步功能时,我们发现过于频繁的同步操作会影响应用性能。最终采用的优化策略包括:
- 防抖处理:用户连续操作时延迟同步
- 批量更新:多个操作合并为一次同步
- 差异对比:只同步变化的部分
-
测试覆盖重点:收藏夹功能的测试应该特别关注:
- 边界情况:收藏大量商品时的性能表现
- 并发操作:多设备同时修改收藏状态
- 数据恢复:应用重启后状态保持
对于想要进一步扩展功能的开发者,可以考虑:
- 增加收藏夹分享功能
- 实现基于AI的智能分类
- 添加价格变动提醒功能
- 开发浏览器插件实现网页内容收藏
