APEALED
APEALED

Reputation: 1663

What implications comes with using a getter pattern rather than a typical immutable member?

Given these two simple design patterns for static values, what are the implications of each of them? Are they identical in performance and memory usage in Dart/Flutter applications when accessing their members?

Example A: MyStringsGetters

const strings = MyStringsGetters();

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

Example B: MyStringsMembers

const strings = MyStringsMembers();

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

Upvotes: 3

Views: 705

Answers (2)

Marius Popescu
Marius Popescu

Reputation: 483

Example A will be more inefficient. Getters are essentially methods that are called at run time and their response is not cached. Yes, the class instance is const and will be stored in memory only once, but the getter will essentially create a new memory address every time you call it.

I would suggest going with Example B.

Here is my proof. I built a dummy app that renders 100 Text instances that display the Hello World string using both examples that you shared and here are the results:

Example A Example B
enter image description here enter image description here

You can clearly see the memory allocated is much smaller in Example B and the main reason is that the getter will allocate new memory addresses.

You can also use the Memory DevTool to play with these kind of questions. Here is the code that I used:

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()),
      ),
    );
  }
}

If you are interested in more tips on how to improve the performance of your Flutter app, I wrote an article here.

Is this documented somewhere?

I tried looking through the documentation and couldn't find much on this. The closest info that I found in the Dart Programming Language Specification book page 37.

Getters are functions (9) that are used to retrieve the values of object properties.

Given that you are not storing the value of the string as an object property and the getter is essentially just a helper function that does what you specify, it will end up allocating memory every time is called. "Hello world" is essentially saying create a new string in memory with this content.

Upvotes: 4

Rahul
Rahul

Reputation: 5049

Kind of. Example A, getter will be called on object of MyStringsGetters. i.e. strings.helloWorld

But example B, helloWorld will be called on MyStringsMembers. i.e. you can't call strings.helloWorld like in Example A.

You should use Example B version if same value is retuned from a getter in a class irrespective of instance (hence the static keyword).

But Example A can be modified to

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;
}

You will get output

Hello World
Thank you

MyClass is still a const which means all the possible values of MyClass will be known as compile time.

Upvotes: 1

Related Questions