实现效果:
需要使用到的第三方网络库:dio
在pubspec.yaml中添加第三方库(相当于Android Studio中的build gradle目录)
dio: ^0.0.14 (dio第三方库名,^后面代表版本号,点击packages get后完成依赖)
使用干货提供的JSON数据。
http://gank.io/api/data/
json格式如下:
{
"error": false,
"results": [
{
"_id": "5b3d883f421aa906e5b3c6f1",
"createdAt": "2018-07-05T10:53:51.361Z",
"desc": "2018-07-05",
"publishedAt": "2018-07-05T00:00:00.0Z",
"source": "web",
"type": "\u798f\u5229",
"url": "http://ww1.sinaimg.cn/large/0065oQSqly1fsysqszneoj30hi0pvqb7.jpg",
"used": true,
"who": "lijinshanmx"
}
]
}
第一步:
建立JSON所对应得model类,解析过程在FLModel.formJson()中处理,对应key即可解析,这里注意类型必须对应,否则解析失败,比如返回String类型,你声明时却是int,这里不会自动转换,导致数据无法解析出来。
/解析类
class FLModle{
final String _id;
final String createdAt;
final String desc;
final String publishedAt;
final String source;
final String type;
final String url;
final bool used;
final String who;
const FLModle(this._id, this.createdAt, this.desc, this.publishedAt, this.source,
this.type, this.url, this.used, this.who);
@override
String toString() {
return 'FLModle{_id: $_id, createdAt: $createdAt, desc: $desc, publishedAt: $publishedAt, source: $source, type: $type, url: $url, used: $used, who: $who}';
}
FLModle.fromJson(Map<String, dynamic> json)
: _id = json['_id'],
createdAt = json['createdAt'],
desc = json['desc'],
publishedAt = json['publishedAt'],
source = json['source'],
type = json['publishedAt'],
url = json['url'],
used = json['used'],
who = json['who'];
}
第二步:
创建一个有状态的组件,继承StatefulWidget,在createState方法中创建我们继承State的组件。
class MeziList extends StatefulWidget{
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return new MeziSateList();
}
}
第三步:创建MeziSateList,继承State组件,可通过setState来更新UI,相当于Android中的runOnUI
(此处内代码放在最后一步编写)。
class MeziSateList extends State<MeziList>{
@override
Widget build(BuildContext context) {
// TODO: implement build
}
}
第四步:
构建网络请求,返回需要的List集合,使用async和await来完成耗时的操作,相当关android中的子线程,Future类似于消息机制(个人观点,只是为了简单理解):
Future<List<FLModle>> _getDate(int pageNum,int pageSize) async{
List flModels;
String url = Constant.baseUrl + '福利/$pageSize/$pageNum';
print(url);
Response response = await dio.get(url);
if(response.statusCode== HttpStatus.OK){//响应成功
flModels = (response.data)['results'] ;
currentpage = currentpage+1;//加载成功后才可加载下一页
}else{//出问题
}
print(flModels.map((model) {
return new FLModle.fromJson(model);
}).toList().length);
return flModels.map((model) {
return new FLModle.fromJson(model);
}).toList();
}
Future<List<FLModle>> feach(int pageNum,int pageSize){
return _getDate(pageNum, pageSize);
}
第四步:编写加载更多和刷新各自对应的逻辑
//刷新时调用
Future<Null> _refreshData(){
final Completer<Null> completer = new Completer<Null>();
currentpage = 1;
feach(currentpage, pageSize).then((list) {
setState(() {
datas = list;
});
}).catchError((error) {
print(error);
});
completer.complete(null);
return completer.future;
}
//加载更多时调用
Future<Null> _loadMoreData(){
final Completer<Null> completer = new Completer<Null>();
feach(currentpage, pageSize).then((list) {
setState(() {
datas.addAll(list);
});
}).catchError((error) {
print(error);
});
completer.complete(null);
return completer.future;
}
第五步:
创建ScrollController来监听ListView的滑动,需要在initState方法中addListener,并且在dispose中removeListener。
/滑动到底了自动加载更多
void _scrollListener(){
if(_scrollController.position.pixels==_scrollController.position.maxScrollExtent){
_loadMoreData();
}
}
//页面初始化时加载数据并实例化ScrollController
@override
void initState() {
// TODO: implement initState
super.initState();
_refreshData();
_scrollController = new ScrollController()..addListener(_scrollListener);
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_scrollController.removeListener(_scrollListener);
}
第六步:
创建item并实现点击事件
Widget buildCardItem(BuildContext context,int index){
final String url = datas[index].url;
return new GestureDetector(//点击事件
onTap: (){
_showPhoto(url);
},
child: new Card(
child: new Container(
padding: EdgeInsets.all(8.0),
child: new Image.network(url),
),
),
);
}
最后一步:
构建ListView,数据加载时显示圆环
@override
Widget build(BuildContext context) {
// TODO: implement build
var content ;
if(datas.isEmpty){
content = new Center(child: new CircularProgressIndicator());;
}else{
content = new ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
itemCount: datas.length,
controller: _scrollController,
itemBuilder: buildCardItem,
);
}
var _refreshIndicator = new RefreshIndicator(
onRefresh: _refreshData,
child: content,
);
return _refreshIndicator;
}
完整代码
import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'dart:async';
import 'progreess_dialog.dart';
import 'package:easy_app/multi_touch_page.dart';
import 'constant.dart';
//解析类
class FLModle{
final String _id;
final String createdAt;
final String desc;
final String publishedAt;
final String source;
final String type;
final String url;
final bool used;
final String who;
const FLModle(this._id, this.createdAt, this.desc, this.publishedAt, this.source,
this.type, this.url, this.used, this.who);
@override
String toString() {
return 'FLModle{_id: $_id, createdAt: $createdAt, desc: $desc, publishedAt: $publishedAt, source: $source, type: $type, url: $url, used: $used, who: $who}';
}
FLModle.fromJson(Map<String, dynamic> json)
: _id = json['_id'],
createdAt = json['createdAt'],
desc = json['desc'],
publishedAt = json['publishedAt'],
source = json['source'],
type = json['publishedAt'],
url = json['url'],
used = json['used'],
who = json['who'];
}
class TabGirlPage extends StatelessWidget{
@override
Widget build(BuildContext context) {
// TODO: implement build
return new Scaffold(
body: new MeziList(),
);
}
}
class MeziList extends StatefulWidget{
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return new MeziSateList();
}
}
class MeziSateList extends State<MeziList>{
List<FLModle> datas = [];//初始化列表数据源
int currentpage = 1;//默认当前页
int pageSize = 10;//每页加载数据
Dio dio = new Dio();//第三方网络加载库
ScrollController _scrollController;
//滑动到底了自动加载更多
void _scrollListener(){
if(_scrollController.position.pixels==_scrollController.position.maxScrollExtent){
_loadMoreData();
}
}
//页面初始化时加载数据并实例化ScrollController
@override
void initState() {
// TODO: implement initState
super.initState();
_refreshData();
_scrollController = new ScrollController()..addListener(_scrollListener);
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_scrollController.removeListener(_scrollListener);
}
@override
Widget build(BuildContext context) {
// TODO: implement build
var content ;
if(datas.isEmpty){
content = new Center(child: new CircularProgressIndicator());;
}else{
content = new ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
itemCount: datas.length,
controller: _scrollController,
itemBuilder: buildCardItem,
);
}
var _refreshIndicator = new RefreshIndicator(
onRefresh: _refreshData,
child: content,
);
return _refreshIndicator;
}
void _showPhoto(String url) {
Navigator.of(context).push(new PageRouteBuilder(
opaque: false,
pageBuilder: (BuildContext context, _, __) {
return new MultiTouchPage(url);
},
transitionsBuilder: (_, Animation<double> animation, __, Widget child) {
return new FadeTransition(
opacity: animation,
child: new RotationTransition(
turns: new Tween<double>(begin: 0.5, end: 1.0).animate(animation),
child: child,
),
);
}));
}
Widget buildCardItem(BuildContext context,int index){
final String url = datas[index].url;
return new GestureDetector(//点击事件
onTap: (){
_showPhoto(url);
},
child: new Card(
child: new Container(
padding: EdgeInsets.all(8.0),
child: new Image.network(url),
),
),
);
}
//刷新时调用
Future<Null> _refreshData(){
final Completer<Null> completer = new Completer<Null>();
currentpage = 1;
feach(currentpage, pageSize).then((list) {
setState(() {
datas = list;
});
}).catchError((error) {
print(error);
});
completer.complete(null);
eturn completer.future;
}
//加载更多时调用
Future<Null> _loadMoreData(){
final Completer<Null> completer = new Completer<Null>();
feach(currentpage, pageSize).then((list) {
setState(() {
datas.addAll(list);
});
}).catchError((error) {
print(error);
});
completer.complete(null);
return completer.future;
}
Future<List<FLModle>> feach(int pageNum,int pageSize){
return _getDate(pageNum, pageSize);
}
Future<List<FLModle>> _getDate(int pageNum,int pageSize) async{
List flModels;
String url = Constant.baseUrl + '福利/$pageSize/$pageNum';
print(url);
Response response = await dio.get(url);
if(response.statusCode== HttpStatus.OK){//响应成功
flModels = (response.data)['results'] ;
currentpage = currentpage+1;//加载成功后才可加载下一页
}else{//出问题
}
print(flModels.map((model) {
return new FLModle.fromJson(model);
}).toList().length);
return flModels.map((model) {
return new FLModle.fromJson(model);
}).toList();
}
}