动态加载ListView
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 import 'package:flutter/material.dart' ;import 'dart:io' ;import 'dart:convert' ;void main() => runApp(MyApp());class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo' , theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: AppBar(title: Text('Flutter Demo' )), body: MyHomeWidget())); } } class MyHomeWidget extends StatelessWidget { @override Widget build(BuildContext context) { return ListView( children: ListTile.divideTiles(context: context, tiles: [ ListTile( leading: Image.network( "https://avatars3.githubusercontent.com/u/6915570?s=460&v=4" ), title: Text('我是标题1' ), subtitle: Text('我是副标题1' ), trailing: Icon(Icons.chevron_right)), ListTile( leading: Image.network( "https://avatars3.githubusercontent.com/u/6915570?s=460&v=4" ), title: Text('我是标题2' ), subtitle: Text('我是副标题2' ), trailing: Icon(Icons.chevron_right)), ListTile( leading: Image.network( "https://avatars3.githubusercontent.com/u/6915570?s=460&v=4" ), title: Text('我是标题3' ), subtitle: Text('我是副标题3' ), trailing: Icon(Icons.chevron_right)), ListTile( leading: Image.network( "https://avatars3.githubusercontent.com/u/6915570?s=460&v=4" ), title: Text('我是标题4' ), subtitle: Text('我是副标题4' ), trailing: Icon(Icons.chevron_right)), ListTile( leading: Image.network( "https://avatars3.githubusercontent.com/u/6915570?s=460&v=4" ), title: Text('我是标题5' ), subtitle: Text('我是副标题5' ), trailing: Icon(Icons.chevron_right)), ]).toList(), ); } }
效果
网络请求实现 1.依赖添加 在pubspec.yaml 文件中添加 http请求依赖
1.添加http
包装 该http
软件包提供了从Internet提取数据的最简单方法。
要安装该http
软件包,请将其添加到pubspec.yaml
文件的“ dependencies”部分。您可以找到pub.dev http
软件包 的最新版本 。
content_copy
1 2 dependencies: http: <latest_version>
导入http包。
content_copy
1 import 'package:http/http.dart' as http;
2.发出网络请求 本食谱介绍如何使用JSONPlaceholder http.get()
方法获取样本专辑 。
content_copy
1 2 3 Future<http.Response> fetchAlbum() { return http.get('https://jsonplaceholder.typicode.com/albums/1'); }
该http.get()
方法返回Future
包含的Response
。
Future
是用于处理异步操作的核心Dart类。Future对象表示将来某个时候可用的潜在值或错误。
本http.Response
类包含一个成功的HTTP调用接收到的数据。
3.将响应转换为自定义Dart对象 发出网络请求很容易,但是使用原始 Future<http.Response>
操作并不是很方便。为了使您的生活更轻松,请将转换http.Response
为Dart对象。
建立Album
课程 首先,创建一个Album
包含来自网络请求的数据的类。它包括一个Album
从JSON 创建一个工厂构造函数。
手动转换JSON只是一种选择。有关更多信息,请参阅JSON和序列化 的完整文章 。
content_copy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Album { final int userId; final int id; final String title; Album({this.userId, this.id, this.title}); factory Album.fromJson(Map<String, dynamic> json) { return Album( userId: json['userId'], id: json['id'], title: json['title'], ); } }
将转换http.Response
为Album
现在,使用以下步骤更新该fetchAlbum()
函数以返回a Future<Album>
:
Map
使用dart:convert
包将响应主体转换为JSON 。
如果服务器确实返回了状态代码为200的OK响应,则 使用factory方法将JSON Map
转换为。Album``fromJson()
如果服务器未返回状态码为200的OK响应,则引发异常。(即使在“ 404未找到”服务器响应的情况下,也会引发异常。请勿返回null
。这在检查中的数据时很重要snapshot
,如下所示。)
content_copy
1 2 3 4 5 6 7 8 9 10 11 12 13 Future<Album> fetchAlbum() async { final response = await http.get('https://jsonplaceholder.typicode.com/albums/1'); if (response.statusCode == 200) { // If the server did return a 200 OK response, // then parse the JSON. return Album.fromJson(json.decode(response.body)); } else { // If the server did not return a 200 OK response, // then throw an exception. throw Exception('Failed to load album'); } }
万岁!现在,您有了一个可以从互联网上获取专辑的功能。
4.提取数据 fetch()
在 initState()
或didChangeDependencies()
方法中调用方法。
该initState()
方法仅被调用一次,然后不再调用。如果您希望选择重新加载API以响应 InheritedWidget
更改,请将该调用放入 didChangeDependencies()
方法中。请参阅State
以获取更多详细信息。
content_copy
1 2 3 4 5 6 7 8 class _MyAppState extends State<MyApp> { Future<Album> futureAlbum; @override void initState() { super.initState(); futureAlbum = fetchAlbum(); }
下一步将使用此Future。
5.显示数据 要在屏幕上显示数据,请使用 FutureBuilder
小部件。该FutureBuilder
小部件随Flutter一起提供,可轻松使用异步数据源。
您必须提供两个参数:
在Future
你想要的工作。在这种情况下,将来从fetchAlbum()
函数返回。
一builder
,告诉扑功能呈现什么,取决于状态Future
:加载,成功或错误。
请注意,snapshot.hasData
仅true
当快照包含非空数据值时才返回。这就是fetchAlbum
即使在“ 404 Not Found”服务器响应的情况下,函数也应引发异常的原因。如果fetchAlbum
返回,null
则微调框将无限期显示。
content_copy
1 2 3 4 5 6 7 8 9 10 11 12 13 FutureBuilder<Album>( future: futureAlbum, builder: (context, snapshot) { if (snapshot.hasData) { return Text(snapshot.data.title); } else if (snapshot.hasError) { return Text("${snapshot.error}"); } // By default, show a loading spinner. return CircularProgressIndicator(); }, );
为什么在initState()中调用fetchAlbum()? 尽管很方便,但不建议将API调用放入build()
方法中。
Flutter build()
每当需要更改视图中的任何内容时都会调用该方法,并且这种情况经常出乎意料地发生。将fetch
调用留在您的build()
方法中会使不必要的调用泛滥到API中,并降低您的应用速度。
完整的例子 content_copy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; Future<Album> fetchAlbum() async { final response = await http.get('https://jsonplaceholder.typicode.com/albums/1'); if (response.statusCode == 200) { // If the server did return a 200 OK response, // then parse the JSON. return Album.fromJson(json.decode(response.body)); } else { // If the server did not return a 200 OK response, // then throw an exception. throw Exception('Failed to load album'); } } class Album { final int userId; final int id; final String title; Album({this.userId, this.id, this.title}); factory Album.fromJson(Map<String, dynamic> json) { return Album( userId: json['userId'], id: json['id'], title: json['title'], ); } } void main() => runApp(MyApp()); class MyApp extends StatefulWidget { //构造函数 接收值 MyApp({Key key}) : super(key: key); @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { Future<Album> futureAlbum; @override void initState() { super.initState(); futureAlbum = fetchAlbum(); } @override Widget build(BuildContext context) { return MaterialApp( title: 'Fetch Data Example', theme: ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: AppBar( title: Text('Fetch Data Example'), ), body: Center( child: FutureBuilder<Album>( future: futureAlbum, builder: (context, snapshot) { if (snapshot.hasData) { return Text(snapshot.data.title); } else if (snapshot.hasError) { return Text("${snapshot.error}"); } // By default, show a loading spinner. return CircularProgressIndicator(); }, ), ), ), ); } }
完整效果