Flutter状态组件的区别和使用——学习记录

638 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情 >>

6.png

状态组件

由于无状态组件在执行过程中只有一个build阶段

在执行期间只会执行一个build函数,没有其他生命周期函数

因此在执行速度和效率方面比有状态组件更好

所以在设计组件时,不要任何组件都使用有状态组件进行开发,要根据实际分析情况使用

Text:文本显示组件,里面包含了文本类相关的样式以及排版相关的配置信息

Image:图片显示组件,里面包含了图片的来源设置,以及图片的配置

Icon: Icon库,里面是Flutter原生支持的一些小的icon FlatButton :包含点击动作的组件

Row:布局组件,在水平方向上依次排列组件

Column:布局组件,在垂直方向上依次排列组件

Container:布局组件,容器组件,这点有点类似于前端中的body

Expanded :可以按比例“伸” Row, Column 和Flex 子组件所占用的Padding :可填充空白区域组件,这点和前端的padding功能基本一致ClipRRect:圆角组件,可以让子组件有圆形边角

由于动态组件和静态组件的特点,因此在组合的时候要非常注意,动态组件下的子组件如果过多。

则在组件更新的时候,会导致其子组件的全部更新,从而引发性能问题

  1. 尽可能减少动态组件下的静态组件
  2. 数据来源相同的部分组合为同一组件
  3. 使用行或者列作为合并的条件
  4. 功能相同的部分,转化为基础组件
  5. 合并后根节点的为Container

快速模仿一个掘金界面

image.png

设计方案

将设计方案分为以下几个过程

1.标记所有界面元素(Flutter基础组件),按照数字进行标记,请注意明显相似部分不需要标记

2.记录相应数字对应的组件名称,并命名展示数据的参数名

3.标记需要交互和数据变化的数据

4.将数字和数据合成一个最小组件,并标记组件是有或无状态组件

5.将第4步中的最小组件进行合并,组件组合规则,请参照上面介绍到的“组件组合要点”

6.完成组件合并后,绘制一张组件图,再次分析动态组件下的静态组件是否合理,如果能拆分尽量拆分

第一步:标记界面元素

将UI或原型的界面元素标记出来,方便我们后面快速设计

image.png

第二步:记录组件名称以及组件数据,标记动态数据

编号基础组件组件作用组件数据是否动态
1Text文章作者nickName
2Text发布日期date
3Text分类category
4CloseButton移除文章/
6Text文章标题title
7Text描述预览summary
8Image文章配图image
9IconButton浏览数browseNum
10IconButton点赞数likeNum
10IconButton评论数comNum

第三步:组件合并

使用画图的方式比较直观一点,我用的 ProcessOn 工具

未命名文件.jpg

项目文件结构实例

根据表格创建相应的目录结构和组件对象,后面的编码过程会相对的简单。

image.png

最终效果

2022-08-21-23-41-18.jpg

练习代码

# home_page.dart

import 'package:flutter/material.dart';

import 'package:f_element/LElement/util.struct/article_summary_struct.dart';
import 'package:f_element/LElement/util.struct/user_info_struct.dart';

import 'package:f_element/LElement/widgets/home_page/article_card.dart';

class HomePage extends StatelessWidget {

  //广告 banner 信息
  final String bannerImage = 'http://5b0988e595225.cdn.sohucs.com/images/20190525/dba69c9a62894ccbb994ded678e5c969.jpeg';
  //用户基本信息
  final UserInfoStruct userInfo = UserInfoStruct(nickname: 'Flutter代码君:', headerIcon: 'https://c-ssl.dtstatic.com/uploads/avatar/202201/01/20220101083802_66eda.thumb.100_100_c.jpeg', commentNum: 221);

  //文章基本信息
  final ArticleSummaryStruct articleInfo = ArticleSummaryStruct(
      title:'淘宝iOS扫一扫架构升级 - 设计模式的应用' ,
      summary:'本文在“扫一扫功能的不断迭代,基于设计模式的基本原则,逐步采用设计模式思想进行代码和架构优化”的背景下,对设计模式在扫一扫中新的应用进行了总结。',
      articleImage:'https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2c73fb8487694dafaccfca73e1e06bed~tplv-k3u1fbpfcp-zoom-crop-mark:3024:3024:3024:1702.awebp?',
      postDate: '2022年08月21日',
      category: 'Flutter',
      comNum: 42,
      browseNum: 5221,
      likeNum:122);

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return ArticleCard(userInfo: userInfo, articleInfo: articleInfo);
  }
}

# article_summary_struct.dart
/*
* 文章信息数据结构
* */
class ArticleSummaryStruct {

  String? title;//文章标题
  String? summary;//描述预览
  String? articleImage;//文章配图
  String? postDate;//文章发表日期
  String? category;//文章分类
  int? likeNum;//点赞数
  int? comNum;//评论数
  int? browseNum;//浏览数
  ArticleSummaryStruct({this.title, this.summary,this.articleImage,this.likeNum,this.comNum,this.browseNum,this.postDate,this.category});
}
# user_info_struct.dart

//用户信息

class UserInfoStruct {
  String? nickname;
  String? headerIcon;
  int? commentNum;
  UserInfoStruct({this.nickname, this.headerIcon, this.commentNum});
}
# article_bottom_bar.dart

import 'package:flutter/material.dart';

class ArticleBottomBar extends StatefulWidget {

  int? likeNum;//点赞数
  int? comNum;//评论数
  int? browseNum;//浏览数

  ArticleBottomBar({Key? key,this.likeNum,this.comNum,this.browseNum}):super(key: key);

  @override
  State<ArticleBottomBar> createState() => _ArticleBottomBarState();
}

class _ArticleBottomBarState extends State<ArticleBottomBar> {

  int likeNum = 0;//点赞数
  int comNum = 0;//评论数
  int browseNum = 0;//浏览数


  void taplike(){
    setState(() {
      print("点赞+1,$likeNum");
      likeNum = likeNum+1;
    });
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    likeNum = widget.likeNum!;
    comNum = widget.comNum!;
    browseNum = widget.browseNum!;
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Row(
      children: [
        IconButton(onPressed: null, icon: Icon(Icons.ad_units_rounded)),
        Text('浏览数:$browseNum'),
        IconButton(onPressed:()=>taplike(), icon: Icon(Icons.thumb_up_off_alt)),
        Text("点赞数:$likeNum"),
        IconButton(onPressed: null, icon: Icon(Icons.comment_outlined)),
        Text("评论数:$comNum"),
      ],
    );
  }
}
# article_card.dart

import 'package:flutter/material.dart';
//数据结构
import 'package:f_element/LElement/util.struct/article_summary_struct.dart';
import 'package:f_element/LElement/util.struct/user_info_struct.dart';
//一级组件
import 'package:f_element/LElement/widgets/home_page/article_bottom_bar.dart';
import 'package:f_element/LElement/widgets/home_page/article_summary.dart';
import 'package:f_element/LElement/widgets/home_page/article_top_bar.dart';


// ArticleCard 属于静态组件只需要继承  StatelessWidget 即可
class ArticleCard extends StatelessWidget {
  //用户信息
  final UserInfoStruct userInfo;
  //帖子信息
  final ArticleSummaryStruct articleInfo;
  //构造函数
  const ArticleCard({Key? key, required this.userInfo, required this.articleInfo}):super(key: key);
  //创建组件
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Column(
      children: [
        ArticleTopBar(nickName: userInfo.nickname,date: articleInfo.postDate,category: articleInfo.category),
        ArticleSummary(title: articleInfo.title,summary: articleInfo.summary,articleImage: articleInfo.articleImage),
        ArticleBottomBar(likeNum: articleInfo.likeNum,browseNum: articleInfo.browseNum,comNum: articleInfo.comNum)
      ],
    );
  }

}
# article_summary.dart
import 'package:flutter/material.dart';

class ArticleSummary extends StatelessWidget {

  final String? title;
  final String? summary;
  final String? articleImage;

  const ArticleSummary({Key? key, this.title, this.summary, this.articleImage}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Row(children: [
      Column(children: [
        SizedBox(width: 250,child: Text(title!, overflow: TextOverflow.clip, style: TextStyle(color: Colors.blue,fontWeight: FontWeight.bold),),),
        SizedBox(width: 230,child: Text(summary!, overflow: TextOverflow.clip),),
        ]
      ),
      Image.network(articleImage!, height: 70)
      // Text(title!,overflow: TextOverflow.ellipsis),
    ]);
  }
}
# article_top_bar.dart
import 'package:flutter/material.dart';

//文章顶部信息
class ArticleTopBar extends StatelessWidget {

  final String? nickName;//文章作者
  final String? date;//发表日期
  final String? category;//分类

  const ArticleTopBar({Key? key,this.nickName,this.date,this.category}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Row(
      children: [
        Text(nickName!),
        Text(date!),
        Text(category!),
        const CloseButton(color: Colors.black, onPressed: null)
      ]
    );
  }
}