这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战。
1. Json转模型
我们在上一篇中处理好了网络请求的数据,接下来就是数据的处理
import 'dart:convert';
复制代码
我们把之前的请求json数据转换为map
var map = json.decode(response.body);
print(map);
复制代码
字典和json
的相互转换
final chatMap = {
'name':'jack',
'message':'helloworld'
};
final chatJson = json.encode(chatMap);
print(chatJson);
复制代码
final newChatModel = json.decode(chatJson);
print(newChatModel["name"]);
print(newChatModel["message"]);
print(newChatModel is Map);
复制代码
关于工厂模式
可以看之前的 文章介绍 构造函数不能有返回值,而factory必须有
class ChatModel{
final String? name;
final String? message;
final String? imageUrl;
ChatModel({this.name,this.message,this.imageUrl});
factory ChatModel.formMap(Map map){
return ChatModel(
name: map['name'],
message: map['content'],
imageUrl: map['image'],
);
}
}
复制代码
我们传一个map字典
返回一个ChatModel的model
;
Future<List<ChatModel>> getListData()
async {
final url = Uri.parse('http://rap2api.taobao.org/app/mock/293940/home/chat/list');
var response = await http.get(url);
if(response.statusCode == 200){
var map = json.decode(response.body);
var listData = map['data'];
return listData.map<ChatModel>((item) => ChatModel.formMap(item)).toList();
}else{
throw Exception('respose code is = ${response.statusCode}');
}
复制代码
这里我们使用Future
。相当于异步函数,配合await
使用,后面会进行学习, 我们判断请求成功就把数组中的数据遍历
返回一个数据模型的数组
。异常的话抛错
2. 布局渲染
我们页面布局使用系统自带的listCell
样式,ListTile
,包含一个头像一个标题和副标题比较符合我们的要求 查看官方的样式
ListTile说明:
实现的效果
调整一下
child: ListView.builder(itemBuilder: (BuildContext context,int index){
return ListTile(
leading: Container(
width: 44,
height: 44,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
image: DecorationImage(
image: NetworkImage(_listData[index].imageUrl!),
)
),
),//头像
title: Text(_listData[index].name!),//姓名
subtitle: Container(
alignment: Alignment.bottomLeft,
padding: EdgeInsets.only(right: 10),
height: 25,
child: Text(_listData[index].message!,overflow: TextOverflow.ellipsis,),//信息,
)
);
},
itemCount: _listData.length,
),
)
复制代码
当我请求数据的时候给个类似loading页的效果
body: _listData.isEmpty ? const Center(
child: Text('页面加载中。。。')
) :ListView.builder(itemBuilder: (BuildContext context,int index)
复制代码
3. 状态保存
我们在切换页面的时候每次都会重新加载widget
页面,很明显不太符合我们的实际需求,我们因此保留这个状态。
主要分为3步,Flutter的开发过程中,首先继承了AutomaticKeepAliveClientMixin
其次重载了wantKeepAlive
方法 返回true
,最后在Widget build(BuildContext context)
调用super.build(context)
。
但是此时切换页面还是加载initState
。是因为我们没有把页面保存到我们的widget树
里面需配合一些控件才能实现效果 比如PageView
,TabBarView
切换之后就不会丢失当前的状态了,也不会再次调用initstate()
方法
class _rootPageState extends State<rootPage> {
@override
int _currentIndex = 0;
List<Widget> _pages = [ChatPage(),FriendPage(),DiscoverPage(),MinePage()];
final PageController _controller = PageController();
Widget build(BuildContext context) {
return Container(
child: Scaffold(
body: PageView(
physics: NeverScrollableScrollPhysics(),
onPageChanged: (int index) {//页面改版的时候
_currentIndex = index;
setState(() {});
},
controller: _controller,
children: _pages,
),
bottomNavigationBar: BottomNavigationBar(
onTap: (index){
setState(() {//页面切换
_currentIndex = index;
_controller.jumpToPage(_currentIndex);
});
},
type: BottomNavigationBarType.fixed,
fixedColor: Colors.green,
currentIndex: _currentIndex,
selectedFontSize: 12,
items: [
BottomNavigationBarItem(
icon: Image.asset('images/tabbar_chat.png', height: 20, width: 20,),
activeIcon: Image.asset('images/tabbar_chat_hl.png', height: 20, width: 20,),
label: "微信"),
BottomNavigationBarItem(
icon:Image.asset('images/tabbar_friends.png',width: 20,height: 20,),
activeIcon: Image.asset('images/tabbar_friends_hl.png',width: 20,height: 20,),
label: '通讯录'),
BottomNavigationBarItem(
icon:Image.asset('images/tabbar_discover.png',width: 20,height: 20,),
activeIcon: Image.asset('images/tabbar_discover_hl.png',width: 20,height: 20,),
label: '发现'),
BottomNavigationBarItem(
icon: Image.asset("images/tabbar_mine.png",width: 20,height: 20,),
activeIcon: Image.asset('images/tabbar_mine_hl.png',width: 20,height: 20,),
label: '我的'),
],
),
),
);
}
}
复制代码
-
_controller.jumpToPage(_currentIndex)
点击底部按钮切换页面 -
physics: NeverScrollableScrollPhysics()
不能拖拽切换页面
相当于PageController
持有children
这些pages
,当我们wantKeepAlive
为true
的时候就不会重载状态initstate()