Flutter ValueListenableBuilder and ValueNotifier 解决组件重绘问题

130 阅读1分钟

一. 使用 leo-editor 记录的对比大纲

如下图所示的关键点对应于源码的相同位置。

ValueNotifier.png

二. 普通实现

import 'dart:math';
import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Value Listenable Builder',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: const MyHomePage(title: 'Value Listenable Builder'),
    );
  }
}
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  var rot = 0;
  @override
  Widget build(BuildContext context) {
    return
      Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body:
          Center(
            child:
              Transform.rotate(
                angle: (rot * (pi / 180)),
                child: _getContainer(),
              ),
          ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            setState(() {
              rot += 30;
              if (rot >= 180) {
                rot = 0;
              }
            });
          },
          child: const Icon(Icons.rotate_right),
        ),
      );
  }
  Container _getContainer() {
    return Container(
      color: Colors.blue,
      height: 300.0,
      width: 300.0,
    );
  }
}

三. 优化实现

import 'dart:math';
import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Value Listenable Builder',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: const MyHomePage(title: 'Value Listenable Builder'),
    );
  }
}
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  var rot = ValueNotifier(0);
  @override
  Widget build(BuildContext context) {
    return
      Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body:
          Center(
            child:
              ValueListenableBuilder(
                valueListenable: rot,
                child: _getContainer(),
                builder: (context, n, c) {
                  return 
                    Transform.rotate(
                      angle: (double.parse(n.toString()) * (pi / 180)),
                      child: c,
                    );
                },
              ),
          ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            rot.value += 30;
            if (rot.value >= 180) {
              rot.value = 0;
            }
          },
          child: const Icon(Icons.rotate_right),
        ),
      );
  }
  Container _getContainer() {
    return Container(
      color: Colors.blue,
      height: 300.0,
      width: 300.0,
    );
  }
}