Flutter学习-19- 微信项目学习-聊天页面展示

这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战

1. Json转模型

我们在上一篇中处理好了网络请求的数据,接下来就是数据的处理

import 'dart:convert';
复制代码

我们把之前的请求json数据转换为map

var map = json.decode(response.body);
print(map);
复制代码

image.png

  • 字典和json的相互转换
final chatMap = {
  'name':'jack',
  'message':'helloworld'
};

final chatJson = json.encode(chatMap);
print(chatJson);
复制代码

image.png

final newChatModel = json.decode(chatJson);
print(newChatModel["name"]);
print(newChatModel["message"]);
print(newChatModel is Map);
复制代码

image.png

关于工厂模式可以看之前的 文章介绍 构造函数不能有返回值,而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,包含一个头像一个标题和副标题比较符合我们的要求 查看官方的样式

image.png

ListTile说明:

image.png

实现的效果

image.png 调整一下

  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,
  ),
)
复制代码

image.png

当我请求数据的时候给个类似loading页的效果

body: _listData.isEmpty ? const Center(

    child: Text('页面加载中。。。')
) :ListView.builder(itemBuilder: (BuildContext context,int index)
复制代码

image.png

3. 状态保存

我们在切换页面的时候每次都会重新加载widget页面,很明显不太符合我们的实际需求,我们因此保留这个状态。
主要分为3步,Flutter的开发过程中,首先继承了AutomaticKeepAliveClientMixin  其次重载了wantKeepAlive 方法  返回true,最后在Widget build(BuildContext context)调用super.build(context)

image.png

但是此时切换页面还是加载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()不能拖拽切换页面

image.png

相当于PageController持有children这些pages,当我们wantKeepAlivetrue的时候就不会重载状态initstate()

Guess you like

Origin juejin.im/post/7031419430651297828