Skip to content

服务生成

使用 flu-cli add service 命令生成业务服务,处理 API 调用、数据存储等。

基本用法

bash
flu-cli add service <name> [options]
flu-cli a service <name> [options]

参数

参数说明
--type服务类型: api, storage, auth(默认: api)
-f, --feature所属功能模块

服务类型

API Service

处理 HTTP 请求:

bash
flu-cli a service user --type api

依赖: http: ^1.1.0

生成的代码:

dart
import 'dart:convert';
import 'package:http/http.dart' as http;

class UserService {
  static const String baseUrl = 'https://api.example.com';

  // GET 请求
  Future<dynamic> getUsers() async {
    try {
      final response = await http.get(
        Uri.parse('$baseUrl/users'),
      );

      if (response.statusCode == 200) {
        return json.decode(response.body);
      } else {
        throw Exception('Failed to load users');
      }
    } catch (e) {
      throw Exception('Error: $e');
    }
  }

  // POST 请求
  Future<dynamic> createUser(Map<String, dynamic> data) async {
    try {
      final response = await http.post(
        Uri.parse('$baseUrl/users'),
        headers: {'Content-Type': 'application/json'},
        body: json.encode(data),
      );

      if (response.statusCode == 201) {
        return json.decode(response.body);
      } else {
        throw Exception('Failed to create user');
      }
    } catch (e) {
      throw Exception('Error: $e');
    }
  }
}

Storage Service

处理本地存储:

bash
flu-cli a service cache --type storage

依赖: shared_preferences: ^2.2.0

生成的代码:

dart
import 'package:shared_preferences/shared_preferences.dart';

class CacheService {
  // 保存字符串
  Future<void> saveString(String key, String value) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString(key, value);
  }

  // 读取字符串
  Future<String?> getString(String key) async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getString(key);
  }

  // 删除
  Future<void> remove(String key) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.remove(key);
  }

  // 清空
  Future<void> clear() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.clear();
  }
}

Auth Service

处理用户认证:

bash
flu-cli a service auth --type auth

依赖: shared_preferences: ^2.2.0

生成的代码:

dart
import 'package:shared_preferences/shared_preferences.dart';

class AuthService {
  static const String _tokenKey = 'auth_token';

  // 保存 Token
  Future<void> saveToken(String token) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString(_tokenKey, token);
  }

  // 获取 Token
  Future<String?> getToken() async {
    final prefs = await SharedPreferences.getInstance();
    return prefs.getString(_tokenKey);
  }

  // 删除 Token
  Future<void> removeToken() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.remove(_tokenKey);
  }

  // 检查是否登录
  Future<bool> isLoggedIn() async {
    final token = await getToken();
    return token != null && token.isNotEmpty;
  }
}

完整示例

创建 API Service

bash
flu-cli a service user -f user --type api

完善 Service

dart
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../models/user_model.dart';

class UserService {
  static const String _baseUrl = 'https://api.example.com';
  final String? _token;

  UserService({String? token}) : _token = token;

  // 获取请求头
  Map<String, String> get _headers => {
    'Content-Type': 'application/json',
    if (_token != null) 'Authorization': 'Bearer $_token',
  };

  // GET - 获取用户列表
  Future<List<User>> getUsers() async {
    try {
      final response = await http.get(
        Uri.parse('$_baseUrl/users'),
        headers: _headers,
      );

      if (response.statusCode == 200) {
        final List<dynamic> data = json.decode(response.body);
        return data.map((json) => User.fromJson(json)).toList();
      } else {
        throw Exception('Failed to load users: ${response.statusCode}');
      }
    } catch (e) {
      throw Exception('Error loading users: $e');
    }
  }

  // GET - 获取单个用户
  Future<User> getUser(String id) async {
    try {
      final response = await http.get(
        Uri.parse('$_baseUrl/users/$id'),
        headers: _headers,
      );

      if (response.statusCode == 200) {
        return User.fromJson(json.decode(response.body));
      } else {
        throw Exception('Failed to load user: ${response.statusCode}');
      }
    } catch (e) {
      throw Exception('Error loading user: $e');
    }
  }

  // POST - 创建用户
  Future<User> createUser(User user) async {
    try {
      final response = await http.post(
        Uri.parse('$_baseUrl/users'),
        headers: _headers,
        body: json.encode(user.toJson()),
      );

      if (response.statusCode == 201) {
        return User.fromJson(json.decode(response.body));
      } else {
        throw Exception('Failed to create user: ${response.statusCode}');
      }
    } catch (e) {
      throw Exception('Error creating user: $e');
    }
  }

  // PUT - 更新用户
  Future<User> updateUser(String id, User user) async {
    try {
      final response = await http.put(
        Uri.parse('$_baseUrl/users/$id'),
        headers: _headers,
        body: json.encode(user.toJson()),
      );

      if (response.statusCode == 200) {
        return User.fromJson(json.decode(response.body));
      } else {
        throw Exception('Failed to update user: ${response.statusCode}');
      }
    } catch (e) {
      throw Exception('Error updating user: $e');
    }
  }

  // DELETE - 删除用户
  Future<void> deleteUser(String id) async {
    try {
      final response = await http.delete(
        Uri.parse('$_baseUrl/users/$id'),
        headers: _headers,
      );

      if (response.statusCode != 204 && response.statusCode != 200) {
        throw Exception('Failed to delete user: ${response.statusCode}');
      }
    } catch (e) {
      throw Exception('Error deleting user: $e');
    }
  }
}

最佳实践

1. 错误处理

统一的错误处理:

dart
class UserService {
  Future<T> _handleRequest<T>(
    Future<http.Response> Function() request,
    T Function(dynamic) parser,
  ) async {
    try {
      final response = await request();

      if (response.statusCode >= 200 && response.statusCode < 300) {
        return parser(json.decode(response.body));
      } else {
        throw ApiException(
          statusCode: response.statusCode,
          message: response.body,
        );
      }
    } on SocketException {
      throw NetworkException('网络连接失败');
    } catch (e) {
      throw ServiceException('请求失败: $e');
    }
  }
}

2. 超时处理

设置请求超时:

dart
class UserService {
  static const Duration _timeout = Duration(seconds: 30);

  Future<List<User>> getUsers() async {
    final response = await http
        .get(Uri.parse('$_baseUrl/users'))
        .timeout(_timeout);
    // ...
  }
}

3. 重试机制

实现请求重试:

dart
class UserService {
  Future<T> _retryRequest<T>(
    Future<T> Function() request, {
    int maxRetries = 3,
  }) async {
    int retries = 0;
    while (true) {
      try {
        return await request();
      } catch (e) {
        retries++;
        if (retries >= maxRetries) rethrow;
        await Future.delayed(Duration(seconds: retries));
      }
    }
  }
}

4. 缓存策略

实现简单缓存:

dart
class UserService {
  final Map<String, dynamic> _cache = {};
  final Duration _cacheDuration = const Duration(minutes: 5);

  Future<List<User>> getUsers({bool forceRefresh = false}) async {
    final cacheKey = 'users';

    if (!forceRefresh && _cache.containsKey(cacheKey)) {
      final cached = _cache[cacheKey];
      if (DateTime.now().difference(cached['time']) < _cacheDuration) {
        return cached['data'] as List<User>;
      }
    }

    final users = await _fetchUsers();
    _cache[cacheKey] = {
      'data': users,
      'time': DateTime.now(),
    };
    return users;
  }
}

5. 依赖注入

使用依赖注入:

dart
// service_locator.dart
final getIt = GetIt.instance;

void setupServices() {
  getIt.registerLazySingleton<UserService>(() => UserService());
  getIt.registerLazySingleton<AuthService>(() => AuthService());
}

// 使用
class UserListViewModel {
  final UserService _service = getIt<UserService>();
}

添加依赖

pubspec.yaml

yaml
dependencies:
    # HTTP 请求
    http: ^1.1.0
    dio: ^5.0.0 # 或使用 dio

    # 本地存储
    shared_preferences: ^2.2.0
    hive: ^2.2.3 # 或使用 hive

    # 依赖注入
    get_it: ^7.6.0

下一步

Released under the MIT License.