How do you build singleton in dart?

The singleton pattern provides only one instance of a class. How to do it in Dart?

+126
singleton dart
Sep 29 '12 at 2:59
source share
12 answers

Thanks to Dart's factory designers, it's easy to assemble a singleton:

class Singleton { static final Singleton _singleton = new Singleton._internal(); factory Singleton() { return _singleton; } Singleton._internal(); } 

You can build it with new

 main() { var s1 = new Singleton(); var s2 = new Singleton(); print(identical(s1, s2)); // true print(s1 == s2); // true } 
+196
Sep 29 '12 at 2:59
source share

Here is a comparison of several different ways to create a singleton in Dart.

1. Factory Designer

 class SingletonOne { SingletonOne._privateConstructor(); static final SingletonOne _instance = SingletonOne._privateConstructor(); factory SingletonOne(){ return _instance; } } 

2. Static field with getter

 class SingletonTwo { SingletonTwo._privateConstructor(); static final SingletonTwo _instance = SingletonTwo._privateConstructor(); static SingletonTwo get instance { return _instance;} } 

3. Static field

 class SingletonThree { SingletonThree._privateConstructor(); static final SingletonThree instance = SingletonThree._privateConstructor(); } 

How to create an instance

The above singletones are created as follows:

 SingletonOne one = SingletonOne(); SingletonTwo two = SingletonTwo.instance; SingletonThree three = SingletonThree.instance; 

Remarks:

I initially asked this as a question , but found that all the methods listed above are valid, and the choice largely depends on personal preferences.

+54
Mar 26 '19 at 0:25
source share

I do not find this very intuitive reading of new Singleton() . You should read the documents to know that new does not actually create a new instance, as usual.

Here's another way to make singletones (basically what Andrew said above).

Library /thing.dart

 library thing; final Thing thing = new Thing._private(); class Thing { Thing._private() { print('#2'); } foo() { print('#3'); } } 

main.dart

 import 'package:thing/thing.dart'; main() { print('#1'); thing.foo(); } 

Note that a singleton is not created until the getter is called for the first time due to delayed Dart initialization.

If you prefer, you can also implement singletones as a static getter for a singleton class. that is, Thing.singleton , not the top-level getter.

Also read how Bob Nystrom talks about the singleton from his book on game programming patterns .

+33
Dec 12 '13 at 23:00
source share

How easy is it to use a global variable in your library, for example?

single.dart :

 library singleton; var Singleton = new Impl(); class Impl { int i; } 

main.dart :

 import 'single.dart'; void main() { var a = Singleton; var b = Singleton; ai = 2; print(bi); } 

Or did it frown?

The syntax pattern is needed in Java, where the concept of globals does not exist, but it seems that you do not need to go far in Dart.

+12
Sep 29
source share

Dart singleton constructor const and factory

 class Singleton { factory Singleton() => const Singleton._internal_(); const Singleton._internal_(); } void main() { print(new Singleton() == new Singleton()); print(identical(new Singleton() , new Singleton())); } 
+9
Dec 20 '13 at 13:00
source share

Here is another possible way:

 void main() { var s1 = Singleton.instance; s1.somedata = 123; var s2 = Singleton.instance; print(s2.somedata); // 123 print(identical(s1, s2)); // true print(s1 == s2); // true //var s3 = new Singleton(); //produces a warning re missing default constructor and breaks on execution } class Singleton { static final Singleton _singleton = new Singleton._internal(); Singleton._internal(); static Singleton get instance => _singleton; var somedata; } 
+9
Sep 25 '14 at 17:35
source share

@Seth Ladd's modified answer for those who prefer the Swift singleton style, e.g. .shared :

 class Auth { // singleton static final Auth _singleton = Auth._internal(); factory Auth() => _singleton; Auth._internal(); static Auth get shared => _singleton; // variables String username; String password; } 

Sample:

 Auth.shared.username = 'abc'; 
+2
Jan 13 '19 at 8:18
source share

Here is a brief example that integrates other solutions. Access to singleton can be made:

  • Using a singleton global variable that points to an instance.
  • Generic Singleton.instance template.
  • Using the default constructor, which is the factory that returns the instance.

Note. Only one of the three options needs to be implemented so that code using a single code is consistent.

 Singleton get singleton => Singleton.instance; ComplexSingleton get complexSingleton => ComplexSingleton._instance; class Singleton { static final Singleton instance = Singleton._private(); Singleton._private(); factory Singleton() => instance; } class ComplexSingleton { static ComplexSingleton _instance; static ComplexSingleton get instance => _instance; static void init(arg) => _instance ??= ComplexSingleton._init(arg); final property; ComplexSingleton._init(this.property); factory ComplexSingleton() => _instance; } 

If you need to perform complex initialization, you just need to do this before using the instance later in the program.

example

 void main() { print(identical(singleton, Singleton.instance)); // true print(identical(singleton, Singleton())); // true print(complexSingleton == null); // true ComplexSingleton.init(0); print(complexSingleton == null); // false print(identical(complexSingleton, ComplexSingleton())); // true } 
+1
Jun 25 '18 at 20:45
source share

Singleton that cannot change object after instance

 class User { final int age; final String name; User({ this.name, this.age }); static User _instance; static User getInstance({name, age}) { if(_instance == null) { _instance = User(name: name, idade: age); return _instance; } return _instance; } } print(User.getInstance(name: "baidu", age: 24).age); //24 print(User.getInstance(name: "baidu 2").name); // is not changed //baidu print(User.getInstance()); // {name: "baidu": age 24} 
+1
Jun 22 '19 at 20:10
source share

That should work.

 class GlobalStore { static GlobalStore _instance; static GlobalStore get instance { if(_instance == null) _instance = new GlobalStore()._(); return _instance; } _(){ } factory GlobalStore()=> instance; } 
0
Oct 13 '18 at 8:31
source share

Since I do not really like to use the new keyword or another constructor, such as calls for singleton, I would prefer to use a static getter with the name inst for example:

 // the singleton class class Dao { // singleton boilerplate Dao._internal() {} static final Dao _singleton = new Dao._internal(); static get inst => _singleton; // business logic void greet() => print("Hello from singleton"); } 

usage example:

 Dao.inst.greet(); // call a method // Dao x = new Dao(); // compiler error: Method not found: 'Dao' // verify that there only exists one and only one instance assert(identical(Dao.inst, Dao.inst)); 
0
Dec 13 '18 at 16:33
source share

Hi, how about this? A very simple implementation, Injector itself is a singleton and also adds classes to it. Of course, it can be extended very easily. If you are looking for something more complex check out this package: https://pub.dartlang.org/packages/flutter_simple_dependency_injection

 void main() { Injector injector = Injector(); injector.add(() => Person('Filip')); injector.add(() => City('New York')); Person person = injector.get<Person>(); City city = injector.get<City>(); print(person.name); print(city.name); } class Person { String name; Person(this.name); } class City { String name; City(this.name); } typedef T CreateInstanceFn<T>(); class Injector { static final Injector _singleton = Injector._internal(); final _factories = Map<String, dynamic>(); factory Injector() { return _singleton; } Injector._internal(); String _generateKey<T>(T type) { return '${type.toString()}_instance'; } void add<T>(CreateInstanceFn<T> createInstance) { final typeKey = _generateKey(T); _factories[typeKey] = createInstance(); } T get<T>() { final typeKey = _generateKey(T); T instance = _factories[typeKey]; if (instance == null) { print('Cannot find instance for type $typeKey'); } return instance; } } 
0
May 09 '19 at 21:56
source share



All Articles