「这是我参与11月更文挑战的第7天,活动概况查看:2021最终一次更文挑战」

回忆

上一篇咱们现已拿到了数据,本章主要讲数据怎样显现。数据显现就不可避免的要说到异步加载以及数据的转换

json转换成字典

Flutter中json数据转换成字典,能够运用json.decode

import 'dart:convert';
json.decode(response.body);

字典转换成模型

结构办法假如想要有返回值,此刻需要运用工厂办法factory

class ChatModel {
  final String? imgUrl;
  final String? name;
  final String? message;
  ChatModel({this.imgUrl, this.name, this.message});
  factory ChatModel.fromMap(Map map) {
    return ChatModel(
        imgUrl: map['imgUrl'], name: map['name'], message: map['message']);
  }
}

模型数据源

异步加载的数据,拿到所有的数据的返回值,能够运用Future

  Future<List<ChatModel>> getData() async {
    final url =
        Uri.parse('http://rap2api.taobao.org/app/mock/293759/home/chat/list');
    var response = await http.get(url);
    if (response.statusCode == 200) {
      // json转换成字典
      final responseBody = json.decode(response.body);
      return responseBody['data']
          .map<ChatModel>((item) => ChatModel.fromMap(item))
          .toList();
      //转模型
    } else {
      throw Exception('statusCode=${response.statusCode}');
    }
  }
}

烘托

有一个专门用来烘托异步加载回来的数据FutureBuilder,有一个必传参数buildercommand点击进去文档是一个有返回值有参数的办法typedef AsyncWidgetBuilder<T> = Widget Function(BuildContext context, AsyncSnapshot<T> snapshot);

Container(
  child: FutureBuilder(
     builder: (BuildContext context, AsyncSnapshot snapshot) {
       print('${snapshot.data}');
       return Container();
    },
    future: getData(),
)),

打印snapshot.data的时分,发现这里会走两次,一次页面刚加载的时分没有拿到数据这里打印的是null,第二次则是拿到数组之后再次刷新数据

Flutter实战-搭建微信项目(七)

snapshot.connectionState:waiting的时分没有数据,done的时分表明数据现已加载完了。

Flutter实战-搭建微信项目(七)
所以此刻咱们能够依据这个connectionState的状况来判断

if (snapshot.connectionState == ConnectionState.waiting) {
       return Center(child: Text('加载中...'));
}

ListView的children能够运用snapshot.data.map<Widget>((ChatModel item)数组遍历生成,一起这里介绍一个新的Widget:ListTile包含比较简单常用的一些布局

const ListTile({
    Key? key,
    this.leading,
    this.title,
    this.subtitle,
    this.trailing,
    this.isThreeLine = false,
    this.dense,
    this.visualDensity,
    this.shape,
    this.contentPadding,
    this.enabled = true,
    this.onTap,
    this.onLongPress,
    this.mouseCursor,
    this.selected = false,
    this.focusColor,
    this.hoverColor,
    this.focusNode,
    this.autofocus = false,
    this.tileColor,
    this.selectedTileColor,
    this.enableFeedback,
    this.horizontalTitleGap,
    this.minVerticalPadding,
    this.minLeadingWidth,
  }) : assert(isThreeLine != null),
       assert(enabled != null),
       assert(selected != null),
       assert(autofocus != null),
       assert(!isThreeLine || subtitle != null),
       super(key: key);

这样布局出来的作用就是这样的:

Flutter实战-搭建微信项目(七)

状况保存

上面有一个小问题,每次页面切出去再次切回来的时分,数据都会从头加载。这样的话状况就没有保存。假如想要保存的话需要:

  1. 继承AutomaticKeepAliveClientMixin

class _ChatPageState extends State<ChatPage> with AutomaticKeepAliveClientMixin

  1. 然后完成父类的办法
  @override
  bool get wantKeepAlive => true;
  1. Widget build(BuildContext context)中完成super.build(context);

修正Widget树

虽然完成了上面的3部曲,可是切回来的时分仍是会从头init,这个是因为在根控制器下每次的页面都是从头生成的,并没有在当时的Widget树中,咱们回到RootPage页面中从头修正一下

  1. 声明一个final PageController _pageController = PageController();
  2. body运用PageView
body: PageView(
  children: _pages,
  controller: _pageController,
),
  1. 切换页面的时分,_pageController同步跳转
setState(() {
   _currentIndex = index;
   _pageController.jumpToPage(_currentIndex);
});

这样每次点击TabbarItem的时分就能保存住当时页面的状况。可是此刻有个小问题,当时的页面能够滑动切屏,可是底部的按钮不会随之联动。这个小问题能够在PageView onPageChanged中处理:

onPageChanged: (index) {
  setState(() {
     _currentIndex = index;
   });
},

或者设置不能拖拽切屏:physics: NeverScrollableScrollPhysics(),

Future

在上面网络请求的时分用到了Future,那么这个到底是什么?

String _temp = '0';
void main() {
  // operatorDemo();
  getData();
  print('循环之前');
}
getData() {
  print('开始了');
  Future(() {
    for (int i = 0; i < 100; i++) {}
    print('循环结束');
  });
}

Flutter实战-搭建微信项目(七)
经过测验发现运用Future修饰的代码块会异步履行,不会卡住当时的线程。假如期望在这个异步使命履行完成之后再操作,需要在Future前面加上一个await

String _temp = '0';
void main() {
  // operatorDemo();
  getData();
  print('循环之前');
}
getData() async {
  print('开始了');
  await Future(() {
    for (int i = 0; i < 100; i++) {}
    print('循环结束');
  });
  print('await之后的代码');
}

Flutter实战-搭建微信项目(七)

完好代码地址:

Flutter实战-搭建微信项目(七)