有状态无状态组件

无状态 StatelessWidget

准备两张图片

const img1 =
    "https://ducafecat.tech/2021/12/09/blog/2021-jetbrains-fleet-vs-vscode/2021-12-09-10-30-00.png";
const img2 =
    "https://ducafecat.tech/2021/12/09/blog/2021-jetbrains-fleet-vs-vscode/2021-12-09-20-45-02.png";

编写图片显示组件 BannerWidget

class BannerWidget extends StatelessWidget {
  const BannerWidget({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Image.network(img1);
  }
}

MyApp 执行

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Column(
          children: const [
            Text('有无状态组件'),
            BannerWidget(),
          ],
        ),
      ),
      debugShowCheckedModeBanner: false,
    );
  }
}

运行

image-20220618055552705

有状态 StatefulWidget

改写成有状态组件

class BannerWidget extends StatefulWidget {
  const BannerWidget({Key? key}) : super(key: key);

  
  State<BannerWidget> createState() => _BannerWidgetState();
}

class _BannerWidgetState extends State<BannerWidget> {
  String? imgUrl;

  
  Widget build(BuildContext context) {
    return Column(
      children: [
        ElevatedButton(
          onPressed: () {
            setState(() {
              imgUrl = imgUrl == img1 ? img2 : img1;
            });
          },
          child: const Text("切换图片"),
        ),
        Image.network(imgUrl ?? img1),
      ],
    );
  }
}

运行

image-20220618060738680

可以发现通过 setState 来管理和维护内部数据状态

有状态包裹无状态组件

编写图片显示组件

class ImageWidget extends StatelessWidget {
  const ImageWidget({Key? key, required this.imgUrl}) : super(key: key);

  final String imgUrl;

  
  Widget build(BuildContext context) {
    return Container(
        padding: const EdgeInsets.all(10),
        color: Colors.amber,
        child: Image.network(imgUrl));
  }
}

这里加了个 Container 显示边框

直接调用

      children: [
        ...
        ImageWidget(
          imgUrl: imgUrl ?? img1,
        ),
      ],

执行

image-20220618062345553

可以发现很多组件都是无状态的,文本、图片、输入框、按钮、卡片、图标...

组件树

image-20220618063344635

使用函数编写组件

编写函数组件

Widget imageWidget({required String imgUrl}) {
  return Container(
    padding: const EdgeInsets.all(10),
    color: Colors.amber,
    child: Image.network(imgUrl),
  );
}

调用

...
imageWidget(
          imgUrl: imgUrl ?? img1,
        ),

查看组件树

image-20220618063630008

可以发现没有显示组件的名称 imageWidget 只是 Container

Flutter 这样做是出于性能考虑,所以如果你是可复用组件,需要用 class 包裹

参考

错误处理

  • 在 macos 中网络请求

macos 网络访问没有权限

修改文件 macos/Runner/DebugProfile.entitlements  和 macos/Runner/Release.entitlements

<key>com.apple.security.network.client</key>
<true/>
Last Updated:
Contributors: ducafecat