Global Variables in Dart
Asked Answered
O

7

139

I try to create a Dart single page application.

I have created a first custom element (custom-application) which contains the whole application. It has a container in it which is used to render views. And a side nav which will contain user informations and be updated when the user is log in.

I want to share informations between views. How can I define a global variable in custom-application and be able to share it with the other views ?

For example, when you start the app, you are not authenticated. When you call /login (login-view) you'll have a login form. I want, when you log in the application, the custom-application element stores the user informations loaded by the nested view login-view and update the side nav.

Is it possible to do it ?

Oleate answered 21/3, 2015 at 12:13 Comment(0)
T
290

Just create a library file and create fields for globals you need there. Import this library everywhere you need access to these fields.

app.dart

import 'globals.dart' as globals;

main() {
  globals.isLoggedIn = true;
}

component1.dart

import 'globals.dart' as globals;

class MyComponent {
  view() {
    if(globals.isLoggedIn) {
      doSomething();
    else {
      doSomethingElse();
    }
  }
}

globals.dart

library my_prj.globals;

bool isLoggedIn = false;

You can also

Tallula answered 21/3, 2015 at 12:21 Comment(10)
It works fine. Thank you for this and all the links. I'm gonna check.Oleate
Sorry, typo. Space should have been a dot.Ephrayim
I've finally succeed to get global variable as observable using the observable pattern. It works very well. Thank you once more.Oleate
@GünterZöchbauer could you explain briefly why this won't work with the compute API?Ridgley
Did I say that? Why do you think it can't work? It's probably better to create a new question where you explain what you try to accomplish, what you tried, and why how failed.Ephrayim
Oops, my apologies - my comment was a bit out of context. No - from the limited tests I've tried, this does not seem to work when globals is accessed from within the callback executed by compute. I'll pose it as a proper question when I get time.Ridgley
@GünterZöchbauer what does library my_prj.globals do in globals.dart file?Borehole
That library declaration was mandatory in earlier Dart versions, but became optional eventually and I think nobody uses it anymore. Every Dart file that is not a part file needs a unique library declaration. When it's not explicitly added it's derived from the file name+path.Ephrayim
@GünterZöchbauer Indeed, the library statement is NOT required. I've just tried to remove it from the code but "the edit queue is full".Dissemble
even this solution didn't solve the problem in flutter web's hot reload. the variables still goes null.Brumley
C
28

You can create a class

myColors.dart

class AppColors {

  static var primary = Colors.blue;
}

And importing your class

import 'package:myapp/.../myColors.dart';

And access with AppColors.primary

Consalve answered 3/4, 2020 at 6:20 Comment(1)
Static variables are not preferred way of accessing and updating variables in dart. Static variables may loose their data across files (see stackoverflow.com/questions/45772318 ).Disembark
C
17

I created a dart file that I called my-globals.dart, where I can define my global variables.

Like this:

library globals;

int globalInt = 0;
bool globalBoolean = true;
String globalString = "";
double globalDouble= 10.0;

That's the whole dart file.

And then, within the same directory or folder I can create other classes, where I can access my globals by importing my-globals.dart as globals. Let's create a class that extends StatefulWidget. There we are going to change the value of the global variable named globalInt by pressing a Flatbutton.

import 'package:flutter/material.dart';
import 'my-globals.dart' as globals;

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

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

class _OtherClassState extends State<OtherClass> {
  @override
  Widget build(BuildContext context) {
    return Container(
       child: FlatButton(
         color: Colors.blue,
         textColor: Colors.white,
         onPressed: () {
            setState(() {globals.globalInt++;});
            print(globals.globalInt);
         },
       ),
    );
  }
}

You see. I just accessed the variable I wanted by writing globals. and then the name of the variable contained in the library.

Hope this example helps to better understand how to use globals library.

Chiliasm answered 8/12, 2020 at 0:5 Comment(0)
S
5

++++ Update July 2019 ++++

I wrote a Package that integrates the Flutter Global Config.

EZ Flutter is a collection of widgets, packages and many more usefull things, mixed up in little framework. The aim is to make standard features available from scratch. EZ Flutter supports managing different configuration files that can be accessed inside the app.

Github : https://github.com/Ephenodrom/EZ-Flutter

dependencies:
  ez_flutter: ^0.2.0

Check out the documentation how using different configurations works.

https://github.com/Ephenodrom/EZ-Flutter/blob/master/documentation/APPLICATION_SETTINGS.md

++++ Old Answer ++++

I had the same problem with global variables. Therefore I also needed different configuration for each app version (dev / prod ) and i don't want to write the configuration in the main_dev.dart or in the main_prod.dart file.

I wrote a simple flutter package that deals with having seperated configuration files and load them at app startup. The configuration is then available at each line of code in your app.

https://github.com/Ephenodrom/Flutter-Global-Config

How to use it :

Create a json file under assets/cfg/$file.json

Add assets/cfg to your pubspec.yaml

Loading different configuration files at app start :

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

void main() async{
  await GlobalConfiguration().loadFromAsset("app_settings");
  await GlobalConfiguration().loadFromAsset("env_dev_settings");
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  ...
}

Using the configuration in your app :

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

class CustomWidget extends StatelessWidget {

    CustomWiget(){
        // Access the config in the constructor
        print(GlobalConfiguration().getString("key1"); // prints value1
    }

    @override
     Widget build(BuildContext context) {
        // Access the config in the build method
        return new Text(GlobalConfiguration().getString("key2"));
     }
}
Stateroom answered 6/12, 2018 at 10:18 Comment(0)
K
2

All you need is create a file like "constants.dart"

import '...materials.dart';

const Color baseColor = Color(0XFF353535);

and use like this

import '...constants.dart';
.......
......


....
Container(
color: baseColor,
.....

),

Korenblat answered 15/7, 2020 at 7:32 Comment(1)
is the question about Variables not constantsSaran
M
0

Based on the library idea, here a way to add "keyed" global variables of any type to a map called from other widgets. This way you do not have to declare such variables beforehand. If a variable does not exist it is added to the map by appDataSet. So in a widget like a checkbox you can add for example in the setState() function: appDataSet('aCheckBox',value); If aCheckBox does not exist in the map it is added and the value is loaded with value (in this case a boolean).

library my_prj.globals;

Map appData = Map<String,dynamic>();

void appDataSet(String key, dynamic value) {
  if (!appData.containsKey(key))
    appData.putIfAbsent(key, () => value);
  else
    appData.update(key, (dynamic) => value);
  print(appData);
}

dynamic appDataGet(String key) {
  if (appData.containsKey(key))
    return (appData.putIfAbsent(key, () => {}));
  else
    return (null);
}
Malpighiaceous answered 1/5, 2020 at 19:21 Comment(0)
D
-2

Global variables are usually frowned upon. A recommended solution for flutter is a provider library. It's just a widget that you insert somewhere high in the widget tree and give it some value (object, class) to hold. Then you access the value deeper inside other widgets.

Opposed to the global variable you can modify value stored by the provider and widgets deep inside will re-render.

pub.dev/provider

Store value

  Widget build(BuildContext context) {
    String someValue = '5';
    return Provider(
            create: (_) => someValue),
            child: SafeArea(...)
    );
  }

Fetch value:

  @override
  void initState() {
    super.initState();

    WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
      setState(() {
        value5 = context.read<String>();
      });
    });
  }
Dimpledimwit answered 30/12, 2021 at 23:23 Comment(3)
Isn't it a bad practice to add a setState on the initState()? This would do an unnecessary rebuild on the whole StatefulWidget scope once loaded. I think it would be better to just bind it to the value5 directly without the WidgetsBinding and setState.Dickens
And to add I think its better to bind the provider value in the didChangeDependency instead of the initState to make sure that the context is readily available.Dickens
When it comes to globals, we use it to store something like API secret key, or CSRF token, which will be used all over the place. We don't need to store in some kind of widget, since they won't change what shown to user.Paisa

© 2022 - 2024 — McMap. All rights reserved.