flutter 使用getter模式而不是典型的不可变成员会带来什么影响?

vx6bjr1n  于 2023-02-05  发布在  Flutter
关注(0)|答案(2)|浏览(133)

给定这两个简单的静态值设计模式,它们各自的含义是什么?当访问它们的成员时,它们在Dart/Flutter应用程序中的性能和内存使用是否相同?

示例A:MyStringsGetters

const strings = MyStringsGetters();

class MyStringsGetters {
  const MyStringsGetters();
  get helloWorld => 'Hello, World';
}

示例B:MyStringsMembers

const strings = MyStringsMembers();

class MyStringsMembers {
  const MyStringsMembers();
  static const helloWorld = 'Hello, World';
}
roejwanj

roejwanj1#

示例A效率会更低。getter本质上是在运行时调用的方法,它们的响应不会缓存。是的,类示例是const,并且只会在内存中存储一次,但getter本质上会在每次调用它时创建一个新的内存地址。

我建议使用示例B
下面是我的证明。我构建了一个虚拟应用程序,使用您分享的两个示例呈现100个文本示例,这些示例显示 Hello World 字符串,以下是结果:
| 示例A|示例B|
| - ------|- ------|
|

|

|
您可以清楚地看到,在Example B中分配的内存要小得多,主要原因是getter将分配新的内存地址。
你也可以使用Memory DevTool来处理这类问题。下面是我使用的代码:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

const strings = MyStringsMembers();

class MyStringsMembers {
  const MyStringsMembers();
  static const helloWorld = 'Hello, World';
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: MyStringsMembers.helloWorld,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

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

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<Widget> _widgets() {
    List<Widget> result = [];
    for (var i = 0; i < 10000; i++) {
      result.add(Text(MyStringsMembers.helloWorld));
    }
    return result;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SingleChildScrollView(
        child: Column(
            mainAxisAlignment: MainAxisAlignment.center, children: _widgets()),
      ),
    );
  }
}

如果您对如何提高Flutter应用程序性能的更多技巧感兴趣,我写了一篇文章here

是否有相关记录

我试着浏览文档,但没有找到太多关于这个的信息。我在Dart Programming Language Specification书的第37页找到了最接近的信息。
getter是用于检索对象属性值的函数(9)。
假设您没有将字符串的值存储为对象属性,并且getter本质上只是一个执行您指定的操作的helper函数,那么每次调用时,它最终都会分配内存。"Hello world"本质上是说使用此内容在内存中创建一个新字符串。

ltskdhd1

ltskdhd12#

类。示例A,getter将在MyStringsGetters的对象上调用,即strings.helloWorld
但是在示例B中,helloWorld将在MyStringsMembers上调用,也就是说,您不能像示例A中那样调用strings.helloWorld
如果从类中的getter返回相同的值而不考虑示例(因此使用了static关键字),则应使用示例B版本。
但示例A可经修改以

void main(){
  print(MyClass("Hello World").value);
  print(MyClass("Thank you").value);
}

class MyClass {
  final String _value;
  const MyClass(String value) : _value=value;
  String get value => _value;
}

您将获得输出

Hello World
Thank you

MyClass仍然是一个const,这意味着MyClass的所有可能值都将被称为编译时。

相关问题