准备工作
- 配置开发环境
https://www.jianshu.com/p/ef700c38f7ba - 接口开放API
https://www.wanandroid.com/blog/show/2 - 项目图片资源
https://www.iconfont.cn/home/index
1、新建项目
先看一下项目首页的效果图
![](https://img.haomeiwen.com/i2020701/aef5d51c30c753e9.jpg)
- 安装完开发环境后,打开Android Studio, New Flutter Project第一次会有点慢,先安装Android Studio开发需要用到的插件,如下图:
![]() |
![]() |
---|
2、添加第三方库
项目会添加dio和flutter_swiper库,下面以dio为例,看看Flutter如何添加第三方库。
-
进入https://pub.dev/,搜索dio
image03.png
-
点击dio进入,然后点击Installing,复制安装版本
image04.png
-
打开项目的pubspec.yaml文件,将 dio: ^3.0.9 粘贴进来,然后点击Packages get
image05.png
2、网络请求工具的封装
import 'package:dio/dio.dart';
class HttpRequest {
static const String baseURL = "https://www.wanandroid.com/";
static const int timeout = 5000;
static final BaseOptions baseOptions =
BaseOptions(baseUrl: baseURL, connectTimeout: timeout);
static final Dio dio = Dio(baseOptions);
static Future<Map<String, dynamic>> request<T>(String url,
{String method = "get",
Map<String, dynamic> params,
Interceptor inter}) async {
final options = Options(method: method);
// 创建默认的全局拦截器
Interceptor dInter = InterceptorsWrapper(onRequest: (options) {
print("\n================== 请求数据 ==========================");
print("url = ${options.uri.toString()}");
print("headers = ${options.headers}");
print("params = ${options.data}");
return options;
}, onResponse: (response) {
print("\n================== 响应数据 ==========================");
print("code = ${response.statusCode}");
print("data = ${response.data}");
return response;
}, onError: (e) {
print("\n================== 错误响应数据 ======================");
print("type = ${e.type}");
print("message = ${e.message}");
return e;
});
List<Interceptor> inters = [dInter];
// 请求单独拦截器
if (inter != null) {
inters.add(inter);
}
// 统一添加到拦截器中
dio.interceptors.addAll(inters);
Response<Map<String, dynamic>> response;
try {
response =
await dio.request(url, queryParameters: params, options: options);
return response.data;
} on DioError catch (e) {
return Future.error(e);
}
}
}
3、数据Json的解析过程
-
创建实体
拷贝网络请求返回的json数据,然后通过FlutterJsonBeanFactory插件新建实体,看下图
image06.png
image07.png
-
dart 异步请求并解析数据
import 'package:flutter_learn/generated/json/banner_entity_helper.dart';
import 'package:flutter_learn/generated/json/home_entity_helper.dart';
import 'package:flutter_learn/model/banner_entity.dart';
import 'package:flutter_learn/model/home_entity.dart';
import 'http_request.dart';
class HomeRequest {
/// 获取banner数据
/// https://www.wanandroid.com/banner/json
static Future<BannerEntity> requestBannerList() async {
final url = "https://www.wanandroid.com/banner/json";
var response = await HttpRequest.request(url);
BannerEntity entity=BannerEntity();
bannerEntityFromJson(entity, response);
return entity;
}
/// 获取首页列表数据
/// http://www.wanandroid.com/article/list/0/json
static Future<HomeEntity> requestHomeList(int start) async {
final url = "/article/list/$start/json";
var response = await HttpRequest.request(url);
HomeEntity homeEntity=HomeEntity();
homeEntityFromJson(homeEntity, response);
return homeEntity;
}
}
4、页面Widget创建
![](https://img.haomeiwen.com/i2020701/af692129ee4bbe0b.png)
- 入口main.dart代码
import 'package:flutter/material.dart';
import 'home/home_page.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter widget',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
- 首页home_page.dart的代码
import 'package:flutter/material.dart';
import 'home_content.dart';
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _currentIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(
index: _currentIndex,
children: pages,
),
bottomNavigationBar: BottomNavigationBar(
selectedFontSize: 14,
unselectedFontSize: 14,
currentIndex: _currentIndex,
type: BottomNavigationBarType.fixed,
items: items,
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
),
);
}
}
//页面list
List<Widget> pages = [
HomePage(),
HomePage(),
HomePage(),
HomePage(),
HomePage(),
];
//bottomNavigationBar item list
List<MyBottomBarItem> items = [
MyBottomBarItem("home", "首页"),
MyBottomBarItem("wechat", "公众号"),
MyBottomBarItem("project", "项目"),
MyBottomBarItem("navigate", "导航"),
MyBottomBarItem("knowledge", "知识体系"),
];
class MyBottomBarItem extends BottomNavigationBarItem {
MyBottomBarItem(String iconName, String title)
: super(
title: Text(title),
icon: Image.asset(
"assets/images/tabbar/$iconName.png",
width: 25,
),
activeIcon: Image.asset(
"assets/images/tabbar/${iconName}_active.png",
width: 25,
),
);
}
- 首页home_content.dart代码
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("首页"),
),
body: Stack(
children: <Widget>[
HomePageContent(),
],
));
}
}
//banner
class BannerContent extends StatefulWidget {
@override
_BannerContentState createState() => _BannerContentState();
}
class _BannerContentState extends State<BannerContent> {
final List<BannerData> bannerList = [];
@override
void initState() {
super.initState();
HomeRequest.requestBannerList().then((BannerEntity entity) {
setState(() {
if (entity.errorCode == 0) {
bannerList.addAll(entity.data);
}
});
});
}
@override
Widget build(BuildContext context) {
return BannerWidget(bannerList: bannerList);
}
}
//列表list
class HomePageContent extends StatefulWidget {
@override
_HomePageContentState createState() => _HomePageContentState();
}
class _HomePageContentState extends State<HomePageContent> {
final List<HomeDataData> homeDataList = [];
@override
void initState() {
super.initState();
HomeRequest.requestHomeList(0).then((HomeEntity entity) {
setState(() {
if (entity.errorCode == 0) {
homeDataList.addAll(entity.data.datas);
}
});
});
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: homeDataList.length,
itemBuilder: (ctx, index) {
if (index == 0) {
return BannerContent();
} else {
return HomeListItem(homeDataList[index]);
}
},
);
}
}
- 列表item home_list_item.dart代码
class HomeListItem extends StatelessWidget {
final HomeDataData data;
HomeListItem(this.data);
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
border:
Border(bottom: BorderSide(width: 8, color: Color(0xffcccccc)))),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
listRow1(),
SizedBox(height: 6),
listRow2(),
SizedBox(height: 6),
listRow3()
],
),
);
}
//列表第一行
Widget listRow1() {
return Row(
children: <Widget>[
Expanded(
flex: 1,
child: Text(data.shareUser, style: TextStyle(color: Colors.grey)),
),
Text(data.niceShareDate, style: TextStyle(color: Colors.grey)),
],
);
}
//列表第一行
Widget listRow2() {
return Text(data.title, style: TextStyle(fontSize: 16));
}
//列表第三行
Widget listRow3() {
return Row(
children: <Widget>[
Expanded(
flex: 1,
child: Text(data.superChapterName+"/"+data.chapterName, style: TextStyle(color: Colors.grey)),
),
Icon(Icons.favorite,color: Color(0xffBFBFBF),size: 18,),
],
);
}
}
- 首页banner
class BannerWidget extends StatelessWidget {
final List<BannerData> bannerList;
BannerWidget({Key key, this.bannerList}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
width: 750,
height: 200,
child: Swiper(
scrollDirection: Axis.horizontal,
// 横向
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () {
//轮播图点击跳转详情页
},
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage("${bannerList[index].imagePath}"),
fit: BoxFit.fill,
)),
));
},
itemCount: bannerList.length,
pagination: new SwiperPagination(
builder: DotSwiperPaginationBuilder(
color: Colors.white.withOpacity(0.5),
activeColor: Colors.white,
),
margin: EdgeInsets.all(10),
),
autoplay: true,
loop: false,
),
);
}
}
5、总结
以前觉得dart嵌套太深,阅读起来很困难, 学了一段时间后,发现控件多进行抽取,阅读起来还可以,源码已上传https://github.com/xulj-tech/flutter_learn,后期继续完成。
网友评论