在上一章完成开发环境的搭建后,本章我们将正式进入代码编写阶段。
一、实现网络请求功能
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))可恢复正常运行。因此建议开发者优先选用低版本模拟器或直接使用真机调试。


雷达卡


京公网安备 11010802022788号







