全部版块 我的主页
论坛 数据科学与人工智能 IT基础
116 0
2025-11-24

在上一章完成开发环境的搭建后,本章我们将正式进入代码编写阶段。

一、实现网络请求功能

1. 引入网络请求依赖库

在 Flutter 项目中进行网络操作时,可以使用官方推荐的 http 库。我们需要先在项目的配置文件中添加该库的依赖。

pubspec.yaml

在文件中加入如下依赖代码:

添加完成后,在终端执行以下命令以下载并安装依赖包:

flutter pub get

当命令执行成功后,表示 http 库已成功集成到项目中。

2. 获取 GitCode 个人访问令牌

登录 GitCode 平台后,进入用户设置页面创建一个新的个人访问令牌(Personal Access Token)。该令牌将用于后续接口的身份验证。

相关 API 文档参考地址:

https://docs.gitcode.com/docs/apis/get-api-v-5-search-users

生成令牌后,需将其安全地保存至代码中以便调用接口时使用。

3. 根据接口响应数据定义实体类

查看 API 返回的数据结构,如下图所示:

根据返回的 JSON 格式,我们可以构建对应的 Dart 实体类来映射数据。

// 用户模型类
class GitCodeUser {
  final String id;
  final String avatarUrl; 
  final String htmlUrl;
  final String createdAt;
  final String? login;
  final String? name;
  final String? email;

  GitCodeUser({
    required this.id,
    required this.createdAt,
    required this.avatarUrl,
    required this.htmlUrl,
    this.login,
    this.name,
    this.email,
  });

  factory GitCodeUser.fromJson(Map<String, dynamic> json) {
    // 处理可能缺失的字段并提供默认值,确保健壮性
    return GitCodeUser(
      id: json['id'] ?? 0,
      createdAt: json['created_at'] ?? '', // 为缺失的created_at提供空字符串
      avatarUrl: json['avatar_url'] ?? '', // 为缺失的avatar_url提供空字符串
      htmlUrl: json['html_url'] ?? '', // 为缺失的html_url提供空字符串
      login: json['login'],
      name: json['name'],
      email: json['email'],
    );
  }
}
// 搜索结果响应模型
import 'package:example/model/GitCodeUser.dart' show GitCodeUser;

class SearchResponse {
  final List<GitCodeUser> items;

  SearchResponse({
    required this.items,
  });

  factory SearchResponse.fromJson(dynamic json) {
    List<dynamic> itemsList;
    if (json is Map<String, dynamic> && json.containsKey('items')) {
      // 标准格式:{"items": [...]}
      itemsList = json['items'];
    } else if (json is List) {
      // 当前提供的格式:[...]直接的用户对象数组
      itemsList = json;
    } else {
      throw FormatException('Unexpected JSON format for SearchResponse');
    }
    
    // 处理URL中的空格和反引号
    final cleanedItems = itemsList.map((item) {
      if (item is Map<String, dynamic>) {
        // 创建item的副本以避免修改原始数据
        final cleanedItem = Map<String, dynamic>.from(item);
        
        // 清理avatar_url字段中的空格和反引号
        if (cleanedItem.containsKey('avatar_url') && cleanedItem['avatar_url'] is String) {
          cleanedItem['avatar_url'] = (cleanedItem['avatar_url'] as String)
              .trim()
              .replaceAll('`', '');
        }
        
        // 清理html_url字段中的空格和反引号
        if (cleanedItem.containsKey('html_url') && cleanedItem['html_url'] is String) {
          cleanedItem['html_url'] = (cleanedItem['html_url'] as String)
              .trim()
              .replaceAll('`', '');
        }
        
        return cleanedItem;
      }
      return item;
    }).toList();
    
    return SearchResponse(
      items: List<GitCodeUser>.from(
        cleanedItems.map((item) => GitCodeUser.fromJson(item)),
      ),
    );
  }
}

4. 编写实际的网络请求逻辑

首先,将之前获取的个人令牌插入到代码适当位置以供请求使用。

接着创建一个名为 GitCodeApiService 的服务类,专门负责处理所有与网络相关的请求。

在具体页面中,即可通过调用该服务类的方法来获取远程数据。

final response = await GitCodeApiService().searchUsers(page,query);

二、实现下拉刷新与上拉加载更多

为了提升用户体验,我们为列表功能增加了刷新和分页加载机制。本示例采用如下组件组合实现:

RefreshIndicator
ListView

配合使用:

controller

主要参数说明:

  • page:当前请求的是第几页数据
  • query:搜索关键词
  • isLoadMore:是否为加载更多操作,false 表示刷新,true 表示加载更多

刷新功能的核心代码如下:

加载更多的实现代码如下:

两者的实现逻辑基本一致,区别在于:
刷新时会重置数据列表,直接替换原有数据;
而加载更多则是在现有数据末尾追加新数据。
同时,加载状态的控制也略有不同。

当数据成功获取后,下一步就是将结果渲染到界面上。

三、功能自测流程

执行运行命令启动应用:

flutter run

项目成功构建并运行后,界面显示如下:

在搜索框中输入目标用户名,点击搜索按钮触发请求。

数据显示正常。当下拉时,列表会重新加载最新数据;当上拉滚动到底部时,会出现加载中的提示,并在请求完成后自动追加新数据。

四、常见问题及解决方案

1. 执行 flutter run 出现错误

在运行 flutter run 命令时,可能出现如下报错信息:

此时建议先执行清理命令:

flutter clean

清理完成后,再次运行项目:

flutter run

2. App 启动时报 Stack Overflow 错误

尽管项目能成功编译,但在模拟器中启动时可能发生崩溃,提示栈溢出错误:

经测试,此问题出现在 Mac 系统环境下,使用 Android SDK 版本 6.0.0(20) 时较为常见。切换至较低版本 SDK(如 5.1.0(18))可恢复正常运行。因此建议开发者优先选用低版本模拟器或直接使用真机调试。

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群