实战示例:网络图片画廊
本示例将展示如何使用 Flu CLI 的网络层和 MVVM 架构,实现一个简单的网络图片画廊功能。
我们将实现:
- API: 调用公开的图片 API。
- Service: 封装网络请求。
- Model: 定义数据模型。
- ViewModel: 处理分页加载逻辑。
- Page: 展示图片瀑布流。
💡 提示: 如果你在创建项目时选择了 "包含网络层",此示例代码通常已经包含在
lib/features/eg_gallery模块中。
1. 定义模型 (Model)
首先定义图片数据结构:
dart
// lib/features/gallery/models/image_model.dart
class ImageModel {
final String id;
final String author;
final String downloadUrl;
ImageModel({
required this.id,
required this.author,
required this.downloadUrl,
});
factory ImageModel.fromJson(Map<String, dynamic> json) {
return ImageModel(
id: json['id'] as String,
author: json['author'] as String,
downloadUrl: json['download_url'] as String,
);
}
}2. 编写服务 (Service)
使用 AppHttp 发起请求。我们使用 picsum.photos 这个免费 API。
dart
// lib/features/gallery/services/gallery_service.dart
import '../../../core/network/app_http.dart';
import '../models/image_model.dart';
class GalleryService {
final AppHttp _http;
GalleryService({AppHttp? http}) : _http = http ?? AppHttp();
/// 获取图片列表 (分页)
Future<List<ImageModel>> fetchImages(int page, int limit) async {
// 示例 API: https://picsum.photos/v2/list?page=1&limit=20
final response = await _http.get(
'https://picsum.photos/v2/list',
queryParameters: {
'page': page,
'limit': limit,
},
);
if (response.isSuccess) {
final list = response.data as List;
return list.map((e) => ImageModel.fromJson(e)).toList();
}
return [];
}
}3. 实现 ViewModel
继承自 BaseListViewModel,它帮我们自动处理了分页、刷新、加载更多状态。
dart
// lib/features/gallery/viewmodels/gallery_viewmodel.dart
import '../../../core/base/base_list_viewmodel.dart';
import '../models/image_model.dart';
import '../services/gallery_service.dart';
class GalleryViewModel extends BaseListViewModel<ImageModel> {
final GalleryService _service = GalleryService();
@override
Future<List<ImageModel>> fetchPage(int page) async {
// 直接调用 Service,返回数据列表
// BaseListViewModel 会把数据追加到 this.list 中
return await _service.fetchImages(page, pageSize);
}
}4. 构建页面 (Page)
继承自 BaseListPage,直接关注列表项 (Item) 的 UI 即可。
dart
// lib/features/gallery/pages/gallery_page.dart
import 'package:flutter/material.dart';
import '../../../core/base/base_list_page.dart';
import '../models/image_model.dart';
import '../viewmodels/gallery_viewmodel.dart';
class GalleryPage extends BaseListPage<GalleryViewModel, ImageModel> {
const GalleryPage({super.key});
@override
_GalleryPageState createState() => _GalleryPageState();
}
class _GalleryPageState extends BaseListPageState<GalleryViewModel, ImageModel, GalleryPage> {
@override
String get title => '图片画廊';
@override
GalleryViewModel createViewModel() => GalleryViewModel();
// 自定义列表项 UI
@override
Widget buildItem(BuildContext context, ImageModel item, int index) {
return Card(
margin: const EdgeInsets.all(8),
child: Column(
children: [
// 图片
AspectRatio(
aspectRatio: 16 / 9,
child: Image.network(
item.downloadUrl,
fit: BoxFit.cover,
loadingBuilder: (ctx, child, progress) {
if (progress == null) return child;
return const Center(child: CircularProgressIndicator());
},
),
),
// 作者名
Padding(
padding: const EdgeInsets.all(8.0),
child: Text('By: ${item.author}'),
),
],
),
);
}
}🎉 效果
运行项目,你将看到:
- 自动进入下拉刷新状态。
- 加载第一页数据并展示图片卡片。
- 滚动到底部自动加载下一页。
- 网络错误时显示错误的界面(点击可重试)。
这就是 Flu CLI Core + Network + MVVM 的强大组合能力,极少量的代码即可实现健壮的列表业务。