本系列同步發表在 個人部落格,歡迎大家關注~
在 github
這套件的加持下,搜尋頁面調用搜尋 API 也變得非常簡單。
在搜尋頁面上我做了以下的調整:
FutureBuilder
來達成異步任務(也就是調用 API)。 @override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder(
future: searchResultList,
builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.done:
if (!snapshot.hasError) {
return ListView.separated(...);
} else {
return Center(child: Text("No Data"));
}
break;
case ConnectionState.none:
case ConnectionState.active:
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
}
},
),
);
}
SearchTypes.repos
調用 githubClient.search.repositories
; SearchTypes.users
調用 githubClient.search.users
。// Search Repos
Future<List<Repository>> searchRepos(String searchQuery) async {
return githubClient.search.repositories(searchQuery).toList();
}
// Search Users
Future<List<User>> searchUsers(String searchQuery) async {
return githubClient.search.users(searchQuery).toList();
}
RepoTile
和 UserTile
。lib/components/github_tiles.dart
import "package:flutter/material.dart";
class RepoTile extends StatelessWidget {
const RepoTile({
Key key,
@required this.name,
this.description,
@required this.stars,
this.language,
}) : super(key: key);
final String name;
final String description;
final int stars;
final String language;
@override
Widget build(BuildContext context) {
return ListTile(
title: Text(name),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(height: 8.0),
description != null
? Text(description)
: Text("No description provided."),
SizedBox(height: 8.0),
Text("★ $stars "),
],
),
trailing: language != null ? Text(language) : SizedBox(),
contentPadding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
onTap: () {},
);
}
}
class UserTile extends StatelessWidget {
const UserTile({
Key key,
this.avatarUrl,
@required this.name,
}) : super(key: key);
final String avatarUrl;
final String name;
@override
Widget build(BuildContext context) {
return ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(avatarUrl),
radius: 16.0,
),
title: Text(name),
dense: true,
onTap: () {},
);
}
}
小提醒:
- 這裡我額外拉出兩個 Widget
RepoTile
和UserList
寫在github_tile.dart
,原因是發現其實還滿多地方會用到他們的,所以就統一寫在一起,方便管理囉~- 有哪些地方還會用到他們? 後續會慢慢看到~
增加 Scrollbar
和 RefreshIndicator
,想必大家不陌生,在本系列 Day 7 時有作講解。
沒印象的可以點 ==> Day7 時光機
顯示搜尋結果上面,預設的函數會顯示 2 pages 60 筆(1 page 為 30 筆資料)。
而通常搜尋到的結果都會出現在前 10 ~ 20 筆(除非你真的找的太冷門...),為了增加搜尋速度,所以把 pages
參數調整為 1。
這裡直接貼上 Commit 的 Diff 圖片給大家參考囉~
--
修改後成果
將前天的倉庫頁,ListTile
的部份替換成剛寫好的 RepoTile
。
而昨天的議題頁,也是將 ListTile
的部份替換成 IssueTile
。
class IssueTile extends StatelessWidget {
const IssueTile({
Key key,
@required this.userAvatarUrl,
@required this.title,
@required this.createTime,
}) : super(key: key);
final String userAvatarUrl;
final String title;
final DateTime createTime;
@override
Widget build(BuildContext context) {
final now = DateTime.now();
final difference = now.difference(createTime);
final createTimeAgo = timeago.format(now.subtract(difference));
return ListTile(
dense: true,
leading: CircleAvatar(
radius: 18.0,
backgroundImage: NetworkImage(userAvatarUrl),
),
title: Text(title),
subtitle: Text(createTimeAgo),
trailing: Icon(Icons.error_outline),
onTap: () {},
);
}
}