133

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 ?

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
T00rk
  • 2,178
  • 3
  • 17
  • 23

7 Answers7

280

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

Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • It works fine. Thank you for this and all the links. I'm gonna check. – T00rk Mar 21 '15 at 12:55
  • Sorry, typo. Space should have been a dot. – Günter Zöchbauer Mar 21 '15 at 14:09
  • 4
    I've finally succeed to get global variable as observable using the observable pattern. It works very well. Thank you once more. – T00rk Mar 23 '15 at 14:51
  • @GünterZöchbauer could you explain briefly why this won't work with the [compute](https://docs.flutter.io/flutter/foundation/compute.html) API? – hunter Aug 30 '18 at 11:09
  • 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. – Günter Zöchbauer Aug 30 '18 at 11:16
  • 2
    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. – hunter Aug 30 '18 at 11:23
  • 5
    @GünterZöchbauer what does `library my_prj.globals` do in `globals.dart` file? – Fadhil Ahmad Feb 12 '20 at 16:35
  • 5
    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. – Günter Zöchbauer Feb 12 '20 at 19:28
  • 1
    @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". – Ian Mar 22 '21 at 17:10
  • even this solution didn't solve the problem in flutter web's hot reload. the variables still goes null. – Taufik Nur Rahmanda Dec 06 '21 at 10:19
27

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

Álvaro Agüero
  • 4,494
  • 1
  • 42
  • 39
  • 1
    This is really simple one! – Reive May 16 '21 at 10:06
  • 4
    Static variables are not preferred way of accessing and updating variables in dart. Static variables may loose their data across files (see https://stackoverflow.com/questions/45772318 ). – Siddy Hacks Aug 27 '21 at 16:47
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.

Iván Yoed
  • 3,878
  • 31
  • 44
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"));
     }
}
Ephenodrom
  • 1,797
  • 2
  • 16
  • 28
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,
.....

),

anonymous
  • 29
  • 3
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);
}
-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>();
      });
    });
  }
Slawa
  • 1,141
  • 15
  • 21
  • 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`. – GhoSt Apr 07 '22 at 00:37
  • 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. – GhoSt Apr 07 '22 at 00:38
  • 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. – Daniel Wu Mar 13 '23 at 08:14