What is static in Flutter

We use the “static” keyword in Dart and Flutter to implement class-wide variables and methods.

In our previous section we have discussed the “extends” keyword in detail. We have seen that an Object can inherit everything from another Object. However, to access the instance variables and methods, we always need to instantiate.

That means we have to create Object. And to connect more objects with each other, we need to create more instances.

Right?

But in Dart and Flutter, we can use the “static” keyword to avoid that.

As a result we can access the class variable or methods with the help of the class name.

It would be a direct access.

We do not have to create an object to access those class variables and methods.

Let us see a simple example.

class Context {
  static const title = 'I am a Context Class variable';
  final String context;
  Context(this.context);
}
main() {
  /// We do not have to instantiate Context
  /// Because title is the Context class variable
  print(Context.title);
  Context context = Context('I am a Context instance variable initialized through Constructor');
  print(context.context); 
}
/**
// output
I am a Context Class variable
I am a Context instance variable initialized through Constructor
*/

In the above code, the class Context defines the “Type” of the Context object. However, when we use the “static” keyword, we do not have to create a Context object to access the class variable “title”.

As a result, we can access the class variable directly. And, we can get the output.

class Context {
  static const title = 'I am a Context Class variable';
...
main() {
  /// We do not have to instantiate Context
  /// Because title is the Context class variable
  print(Context.title);
...
// output: I am a Context Class variable

But in case of the “instance variable”, we have to create the object first.

Context context = Context('I am a Context instance variable initialized through Constructor');
  print(context.context);

Let us try to emulate the same thing in Flutter.

To do that, we need to initialize a constant String value with the “static” keyword.

import 'package:flutter/material.dart';

main() {
  runApp(const App());
}

class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  static const title = 'Class Variables and Methods';

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: title,
      home: AppHomePage(),
    );
  }
}

class AppHomePage extends StatelessWidget {
  const AppHomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(App.title),
      ),
      body: Center(
        child: Text(
          App.title,
          style: Theme.of(context).textTheme.headline4,
        ),
      ),
    );
  }
}

We have already learned that in Flutter everything is Widget. That means, everything is Class. Or, in other words every Object has its custom “Type”.

In any Flutter App the top-level main() function is the entry point.

We call the function runApp() and pass the root Widget or Class.

main() {
  runApp(const App());
}

Now, this “App()” is a class constructor.

Therefore we need to create the App() class or widget and extend it to a Stateless Widget.

Moreover, we use the “static” keyword inside that App() class.

Why?

To create a “Class Variable” called “title”.

Subsequently, we can access the “title” with the Class name later.

return Scaffold(
      appBar: AppBar(
        title: const Text(App.title),
      ),
      body: Center(
        child: Text(
          App.title,
          style: Theme.of(context).textTheme.headline4,
        ),
      ),
    );

If we run the Flutter App, we can see the output on the screen.

Flutter static keyword and class variable

Since we do not have to create an Object, the class variable is much faster than the instance variable.

However, we can build the similar Flutter App with the help of an instance variable.

To do that, we need to pass the same String type “title” through the Widget constructor. Then we use the “named constructor”.

import 'package:flutter/material.dart';

main() {
  runApp(const App(
    title: 'Initialising Instance variable',
  ));
}

class App extends StatelessWidget {
  const App({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: title,
      home: AppHomePage(
        title: title,
      ),
    );
  }
}

class AppHomePage extends StatelessWidget {
  const AppHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Text(
          title,
          style: Theme.of(context).textTheme.headline4,
        ),
      ),
    );
  }
}

The same output on the screen, but the value of the instance variable is different now.

Flutter instance variable
Flutter instance variable

We do not want to form any opinion about it. Neither we do not want to pass any judgement on what is the best practice.

In some cases, we need the the class Variables and methods. In some other cases, we need the instance variables and methods.

It depends on the context.

In Dart, however, we can test the both in various ways.

class Context {
  static const _title = 'I am a Context Class variable';
  String? context;
  Context({this.context});
}
class StateLess {
  String? state;
  Context? context;
  StateLess({this.state, this.context});
  void build(Context context) {
    context = context;
    print('I am building the ${context.runtimeType} Type');
  }
}
class Text extends StateLess {
  String? text;
  Text(this.text);
  @override
  void build(Context context) {
    print('I am overriding the build method with ${text.runtimeType} Type');
  }
}
main() {
  /// We do not have to instantiate Context
  /// Because _title is the Context class variable
  print(Context._title);
  
  Text textInstance = Text('I am Text');
  
  /// we can instantiate a Context Object through Text Object
  /// because we have inherited Context Object from Stateless Class
  textInstance.context = Context(context: 'I am Context for Text');
  
  /// now we can check the Type of the Context Object that we 
  /// have instantated through Text Object
  print('Type of the Context Object that we have instantated ' 
        'through Text Object is ' 
        '${textInstance.context.runtimeType}');
  textInstance.context!.context = Context._title;
  
  textInstance.context!.context = 'I have changed Context Title';
  var aNewContextTitleChangedThroughTextClass = textInstance.context!.context;
  print(aNewContextTitleChangedThroughTextClass); 
 
}

If we run the above code, we get the following output.

I am a Context Class variable
Type of the Context Object that we have instantated through Text Object is Context
I have changed Context Title

In the coming section we will take a look on Abstract class, Interface and Mixins.

So stay tuned.

What Next?

Books at Leanpub

Books in Apress

My books at Amazon

GitHub repository

Technical blog

Twitter

Comments

3 responses to “What is static in Flutter”

  1. […] we can use more abstraction. We can declare a function as an instance variable. And, we can pass the variable through class […]

  2. […] But for the “const” keyword it is not allowed. In fact, if we want to assign a value to a const variable inside a class, we need to make it static. We have discussed the “static” keyword before. […]

  3. […] we can use more abstraction. We can declare a function as an instance variable. And, we can pass the variable through class […]

Leave a Reply