欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

本人的学习灵感源自 CSDN 博主 A 懿轩 A(博客链接:https://blog.csdn.net/2301_80035882?type=blog)。博主围绕【2025 版 OpenHarmony】AtomGit 口袋工具系列开发内容,兼具实用性与指导性,极具参考和学习意义。在此基础上所有内容均为个人实操总结,尊重原作者知识产权,特此标注。

前言

本文为 Flutter for OpenHarmony 系列开发笔记第十篇,基于 AtomGit 口袋工具 v1.0.3 版本,从UI 组件封装、异常容错处理、输入参数校验三个维度进行代码优化,解决原项目中代码冗余、容错性差、参数异常导致的功能故障问题,提升代码的可维护性、复用性和应用稳定性,同时优化用户体验,适合有基础的 Flutter/OpenHarmony 开发者学习。

一、优化背景

原 AtomGit 口袋工具源码实现了基础功能,但存在以下问题:

  1. UI 代码冗余:多个页面使用相同的图标 + 标题 + 内容区块,重复编写代码,维护成本高;
  2. 容错性不足:头像加载仅支持单一路径,本地 / 网络图片加载失败后无兜底方案;
  3. 参数校验缺失:用户输入含空格、分页参数超出范围时,会导致接口 404 / 服务器报错;
  4. 异常提示不友好:参数错误时无明确的异常信息,用户无法快速定位问题。

本次优化针对以上问题,分别在 UI 层、数据层、网络层进行针对性改造。

二、优化一:UI 组件封装与复用(减少代码冗余)
2.1 优化场景

项目中intro_page.dartprofile_page.dart等多个页面使用图标 + 标题 + 内容的统一风格区块,原代码重复编写,需封装为通用组件。

2.2 优化原理

创建通用构建方法_buildSection,接收标题、图标、内容三个必传参数,统一生成风格一致的 UI 区块,支持全局复用,修改时仅需修改通用方法,无需逐个页面调整。

2.3 实现代码(路径:lib/pages/main_navigation/intro_page.dart)
// 通用区块构建方法,统一生成图标+标题+内容风格的UI组件
// [context]:BuildContext上下文
// [title]:区块标题(必传)
// [icon]:区块图标(必传,IconData类型)
// [child]:区块内容组件(必传,Widget类型)
Widget _buildSection(
  BuildContext context, {
  required String title,
  required IconData icon,
  required Widget child,
}) {
  final theme = Theme.of(context);
  return Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      // 标题栏(图标+文字)
      Row(
        children: [
          Icon(icon, color: theme.colorScheme.primary, size: 24),
          const SizedBox(width: 8), // 图标与文字间距
          Text(
            title,
            style: theme.textTheme.titleLarge?.copyWith(
              fontWeight: FontWeight.bold,
            ),
          ),
        ],
      ),
      const SizedBox(height: 16), // 标题与内容间距
      child, // 自定义内容区域(支持传入任意Widget)
    ],
  );
}

2.4 使用方式

// 替代原重复的UI代码,一行调用即可生成统一风格的区块
_buildSection(
  context,
  title: "功能特性",
  icon: Icons.featured_play_list,
  child: _buildFeatureList(), // 自定义内容组件
),
2.5 优化效果
  1. 减少约 60% 的 UI 重复代码,项目代码量大幅精简;
  2. 统一全局 UI 风格,避免多个页面风格不一致;
  3. 后续修改区块样式时,仅需修改_buildSection方法,实现一处修改,全局生效
三、优化二:头像加载容错处理(层层保底,避免加载失败)
3.1 优化场景

原项目中头像仅支持单一路径加载,本地图片 / 网络图片加载失败后,页面会显示空白,用户体验差,需添加多层容错兜底。

3.2 优化原理

采用本地图片→网络图片→默认图标的三级加载策略,通过errorBuilder捕获图片加载异常,异常后自动切换到下一级加载方式,确保头像始终有内容显示。

3.3 实现代码(路径:lib/pages/main_navigation/profile_page.dart)
// 头像组件(三级容错加载)
Container(
  width: 120,
  height: 120,
  decoration: BoxDecoration(
    shape: BoxShape.circle, // 圆形裁剪
    border: Border.all(
      color: theme.colorScheme.primary.withValues(alpha: 0.3), // 半透明主色边框
      width: 3,
    ),
    boxShadow: [
      BoxShadow(
        color: theme.colorScheme.primary.withValues(alpha: 0.2), // 柔和阴影
        blurRadius: 20,
        offset: const Offset(0, 10),
      ),
    ],
  ),
  child: ClipOval(
    child: Image.asset(
      avatarUrl, // 第一级:优先加载本地头像
      fit: BoxFit.cover,
      errorBuilder: (context, error, stackTrace) {
        // 本地加载失败,触发第二级:加载网络头像
        return Image.network(
          fallbackAvatarUrl,
          fit: BoxFit.cover,
          errorBuilder: (context, error, stackTrace) {
            // 网络加载失败,触发第三级:显示默认用户图标
            return Container(
              color: theme.colorScheme.surfaceContainerHighest,
              child: Icon(
                Icons.person,
                size: 60,
                color: theme.colorScheme.onSurfaceVariant,
              ),
            );
          },
        );
      },
    ),
  ),
),
3.4 优化效果
  1. 彻底解决头像加载失败导致的页面空白问题;
  2. 三级加载策略适配不同网络 / 本地资源场景,提升鲁棒性;
  3. 加入边框和阴影样式,优化头像视觉效果。
四、优化三:输入参数预处理与校验(避免接口异常)
4.1 优化场景

原项目中用户输入的用户名 / 搜索关键词含空格、分页参数(per_page/page)超出合理范围时,会导致接口 404 错误、服务器报错,甚至一次性加载大量数据导致应用卡顿,需在网络请求前对参数进行预处理和校验。

4.2 优化原理
  1. 参数清洗:通过trim()去除用户输入的前后空格,避免无效查询;
  2. 非空校验:清洗后参数为空时,抛出明确的异常信息,阻止无效网络请求;
  3. 范围校验:通过clamp(min, max)限制分页参数的范围,确保参数在服务器允许的合理区间内。
4.3 实现一:用户名 / 关键词清洗与非空校验(路径:lib/core/atomgit_api.dart)
/// 通过登录名获取用户详情,可选地携带token进行授权访问
Future<GitCodeUser>fetchUser(
  String? personalToken, String username,{
  bool allowSearchFallback = true,
}) async {
  // 统一去除前后空白,避免用户误输入空格导致请求404
  final trimmed = username.trim();
  // 非空校验,为空则抛出明确异常
  if (trimmed.isEmpty) {
    throw const GitCodeApiException('用户名不能为空');
  }
  // 后续网络请求逻辑...
}

/// 用户搜索接口参数校验
Future<List<GitCodeUser>> searchUser(
  String? personalToken, String keyword,{
  int page = 1,
  int perPage = 20,
}) async {
  // 搜索关键词清洗与非空校验
  final trimmed = keyword.trim();
  if (trimmed.isEmpty) {
    throw const GitCodeApiException('请输入搜索关键字');
  }
  // 后续网络请求逻辑...
}

4.4 实现二:分页参数范围校验(路径:lib/core/atomgit_api.dart)

final response = await _dio.get<List<dynamic>>(
  '/search/users',
  queryParameters: <String, dynamic>{
    'q': trimmed,
    'access_token': personalToken,
    // clamp限制参数范围:per_page[1,50],page[1,100],避免后端报错
    'per_page': perPage.clamp(1, 50),
    'page': page.clamp(1, 100),
  },
);
4.5 优化效果
  1. 彻底避免因用户误输入空格导致的接口 404 错误;
  2. 分页参数被限制在合理范围,防止一次性加载大量数据导致应用卡顿 / 崩溃;
  3. 抛出明确的异常信息,方便用户快速定位问题,提升使用体验;
  4. 减少无效的网络请求,降低服务器压力。

五、整体优化总结

本次三大核心优化从开发效率、应用稳定性、用户体验三个维度提升了 AtomGit 口袋工具的质量,优化前后对比:

优化维度 优化前 优化后
UI 代码 重复编写,维护成本高 通用封装,一处修改全局生效
容错性 加载失败无兜底,页面空白 三级加载策略,始终有内容显示
参数校验 无校验,易导致接口异常 清洗 / 非空 / 范围校验,避免无效请求
异常提示 无明确信息,用户无法定位问题 自定义异常信息,提示清晰
代码可维护性 低,冗余代码多 高,模块化、复用性强
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐