今日的程序码 => GIHUB
这篇,我要请求 https://jsonplaceholder.typicode.com/posts/ 这个网址的资料,并显示在手机上面。
怎麽使用 API 的话,可以查看 前一篇 的文章。
可以看到下方,我们定义了一个 enmu,里面是状态。
下面则是定义一个私有的 sortState
和公开的 sortState
,和 post
资料。
底下是一个 fetchData
的方法。他会去 call Api
。当我们把 api
的资料拿到手後。我们就开始排序。最後我们排序完成後需要使用 notifyListeners
,告知控制器,资料已经被更新。
enum SortState { sortWithId, sortWithTitle, sortWithBody, sortWithUserId }
class PostProvider extends ChangeNotifier {
PostRepository _postRepository = PostRepository();
SortState _sortState = SortState.sortWithId;
SortState get sortState => _sortState;
List<PostModel> _posts = [];
List<PostModel> get posts => _posts;
fetchData(SortState sortState) async {
_sortState = sortState;
_posts = await _postRepository.fetchData();
if (_sortState == SortState.sortWithId) {
_posts.sort((a, b) => a.id.compareTo(b.id));
} else if (_sortState == SortState.sortWithTitle) {
_posts.sort((a, b) => a.title.compareTo(b.title));
} else if (_sortState == SortState.sortWithBody) {
_posts.sort((a, b) => a.body.compareTo(b.body));
} else if (_sortState == SortState.sortWithUserId) {
_posts.sort((a, b) => a.userId.compareTo(b.userId));
}
notifyListeners();
}
}
MultiProvider
元件是一个初始化的共享装置元件。
这边我们在 MaterialApp
外面建立了一个 MultiProvider
,代表只要在 MaterialApp
里面都可以取到 PostProvider
的资料。
return MultiProvider(
providers: [
ChangeNotifierProvider<PostProvider>(
create: (context) => PostProvider(),
),
],
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
),
);
单存呼叫控制器的方法。
context.read<PostProvider>().fetchData(SortState.sortWithId);
读取资料 watch
,这个方式只要有呼叫触发 notifyListeners
,他就会重新去读取资料,不管这笔资料的值是否和原先的不一样,他都会重新 rebuild widget。使用方式可以在 build
方法里面的 return Widget 里面直接使用。
@override
Widget build(BuildContext context) {
return Text(context.watch<PostProvider>().posts[1].body);
}
读取资料 select
,这是方法需要满足以下条件
notifyListener
context.select
需要放在 return
外面@override
Widget build(BuildContext context) {
var posts = context.select((PostProvider p) => p.posts);
return Text(posts[1].body);
}
注意:
在这边,我分享一个 ISSUE。
可以看到 select relies on the value obtained to be immutable
。
因此如果我们使用 select
的方式,就要把我们的 provider
里面要更改成这样
_posts = [..._posts];
_posts.sort((a, b) => a.id.compareTo(b.id));
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
// 一进到画面就取资料
context.read<PostProvider>().fetchData(SortState.sortWithId);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: <Widget>[
PopupMenuButton(
icon: Icon(Icons.more_vert),
itemBuilder: (context) => [
PopupMenuItem(
child: Text('使用 userId 排序'),
value: SortState.sortWithUserId,
),
PopupMenuItem(
child: Text('使用 id 排序'),
value: SortState.sortWithId,
),
PopupMenuItem(
child: Text('使用 title 排序'),
value: SortState.sortWithTitle,
),
PopupMenuItem(
child: Text('使用 body 排序'),
value: SortState.sortWithBody,
)
],
onSelected: (SortState value) {
context.read<PostProvider>().fetchData(value);
})
],
),
body: MyListView());
}
}
class MyListView extends StatelessWidget {
const MyListView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: context.watch<PostProvider>().posts.length,
itemBuilder: (context, index) {
var post = context.watch<PostProvider>().posts[index];
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(16)),
color: Colors.white,
border: Border.all(color: Colors.blueAccent, width: 2.0)),
margin: EdgeInsets.all(8),
padding: EdgeInsets.all(8),
child: RichText(
text: TextSpan(
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(
text: post.id.toString() + ". " + post.title,
style: TextStyle(fontSize: 18, color: Colors.red),
),
TextSpan(
text: '\n' + post.body,
style: TextStyle(fontWeight: FontWeight.bold),
),
TextSpan(
text: "\nUser ID:" + post.userId.toString(),
style: TextStyle(fontSize: 18),
),
],
),
));
},
);
}
}
>>: Day 17:专案03 - PTT 八卦版爬虫02 | session、post
今日文章目录 > - 导览列 > - 练习演示 > - 遇到的问题 > -...
Preface 由於之後我们会解说到像是Gin搭配RDBMS或是Gin搭配Cache....等,因此...
题目 美术馆有n 种票,票价为 p1、p2、p3 直到 pn,所需张数为 x1、x2、x3 直到 x...
目的 当有大量重复物件时,抽离物件相同部分的资料,并用专属的工厂管理,好减少重复的资料,减少记忆体的...
前端的社群发展愈来愈蓬勃,延伸出各式各样基於 HTML、CSS、JS 的开源套件,像是 Bootst...