Flutter ListView懒加载(滑动不加载,停止滑动加载)

4,844 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

前言:为了更好的减小网络的带宽,使得列表更加流畅,我们需要了解懒加载,也称延迟加载。 面试真题:flutter如何实现懒加载?

关于上一章的登录界面,各位属实难为我了,我也在求ui小姐姐,各位点点赞给我点动力吧~

5e3c9f11dc5c8d53c46907cf16e2b5e.jpg ca.png

image.png

懒加载也叫延迟加载,指的是在长网页中延迟加载图像,是一种很好优化网页性能的方式。用户滚动到它们之前,可视区域外的图像不会加载。这与图像预加载相反,在长网页上使用延迟加载将使网页加载更快。在某些情况下,它还可以帮助减少服务器负载。常适用图片很多,页面很长的电商网站场景中。

对ListView优化就那么几点:(后面都会写出来):

1.Flutter ListView加载图片优化(懒加载)

2.Flutter ListView加载时使用图片使用缩略图,对图片进行缓存

3.Flutter 减少build()的耗时

本章,我们会实现wechat朋友圈的优化功能,即当页面在滑动时不加载图片,在界面停止滑动时加载图片。
效果图:

tt0.top-288153.gif

1.了解widget通知监听:NotificationListener

NotificationListener属性:

  • child:widget
    
  • onNotification:NotificationListenerCallback<Notification>
    

    返回值true表示消费掉当前通知不再向上一级NotificationListener传递通知,false则会再向上一级NotificationListener传递通知;这里需要注意的是通知是由下而上去传递的,所以才会称作冒泡通知!

2.需要一个bool来控制是否加载

///加载图片的标识
bool isLoadingImage = true;

3.编写传递通知的方法,使其作用于NotificationListener

bool notificationFunction(Notification notification) {
  ///通知类型
  switch (notification.runtimeType) {
    case ScrollStartNotification:
      print("开始滚动");
​
      ///在这里更新标识 刷新页面 不加载图片
      isLoadingImage = false;
      break;
    case ScrollUpdateNotification:
      print("正在滚动");
      break;
    case ScrollEndNotification:
      print("滚动停止");
​
      ///在这里更新标识 刷新页面 加载图片
      setState(() {
        isLoadingImage = true;
      });
      break;
    case OverscrollNotification:
      print("滚动到边界");
      break;
  }
  return true;
}

4.根据bool值加载不同的组件

ListView buildListView() {
  return ListView.separated(
    itemCount: 1000, //子条目个数
    ///构建每个条目
    itemBuilder: (BuildContext context, int index) {
      if (isLoadingImage) {
        ///这时将子条目单独封装在了一个StatefulWidget中
        return Image.network(
          netImageUrl,
          width: 100,
          height: 100,
          fit: BoxFit.fitHeight,
        );
      } else {
        return Container(
          height: 100,
          width: 100,
          child: Text("加载中..."),
        ); //占位
      }
    },
​
    ///构建每个子Item之间的间隔Widget
    separatorBuilder: (BuildContext context, int index) {
      return new Divider();
    },
  );
}

完整代码:

class ScrollHomePageState extends State {
  ///加载图片的标识
  bool isLoadingImage = true;
​
  ///网络图片地址
  String netImageUrl =
      "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0a4ce25d48b8405cbf5444b6195928d4~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp";
​
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        title: Text("详情"),
      ),
      ///列表
      body: NotificationListener(
        ///子Widget中的滚动组件滑动时就会分发滚动通知
        child: buildListView(),
        ///每当有滑动通知时就会回调此方法
        onNotification: notificationFunction,
      ),
    );
  }
​
  bool notificationFunction(Notification notification) {
    ///通知类型
    switch (notification.runtimeType) {
      case ScrollStartNotification:
        print("开始滚动");
​
        ///在这里更新标识 刷新页面 不加载图片
        isLoadingImage = false;
        break;
      case ScrollUpdateNotification:
        print("正在滚动");
        break;
      case ScrollEndNotification:
        print("滚动停止");
​
        ///在这里更新标识 刷新页面 加载图片
        setState(() {
          isLoadingImage = true;
        });
        break;
      case OverscrollNotification:
        print("滚动到边界");
        break;
    }
    return true;
  }
​
  ListView buildListView() {
    return ListView.separated(
      itemCount: 1000, //子条目个数
      ///构建每个条目
      itemBuilder: (BuildContext context, int index) {
        if (isLoadingImage) {
          ///这时将子条目单独封装在了一个StatefulWidget中
          return Image.network(
            netImageUrl,
            width: 100,
            height: 100,
            fit: BoxFit.fitHeight,
          );
        } else {
          return Container(
            height: 100,
            width: 100,
            child: Text("加载中..."),
          ); //占位
        }
      },
​
      ///构建每个子Item之间的间隔Widget
      separatorBuilder: (BuildContext context, int index) {
        return new Divider();
      },
    );
  }
}

是不是很简单,但是懒加载确实是面试真题,你了解了吗?

ad.png