Question #8MediumFlutter BasicsImportant

Diff btw stateless and stateful widget and explain

#widget#state

Answer

Overview

StatelessWidget and StatefulWidget are the two fundamental widget types in Flutter. The key difference is that StatefulWidget can change over time (mutable state), while StatelessWidget cannot (immutable).


Comparison Table

FeatureStatelessWidgetStatefulWidget
StateImmutable (cannot change)Mutable (can change)
RebuildOnly when parent rebuildsCan rebuild with setState()
LifecycleSimple (build() only)Complex (multiple methods)
PerformanceFaster (less overhead)Slightly slower
MemoryLess memoryMore memory (State object)
Use CaseStatic UIDynamic/Interactive UI
ExamplesText, Icon, ImageCheckbox, TextField, Animations

StatelessWidget

Definition

A widget that never changes once built. Immutable configuration.

Structure

dart
class WelcomeScreen extends StatelessWidget {
  final String userName;
  
  const WelcomeScreen({required this.userName});
  
  
  Widget build(BuildContext context) {
    return Text('Welcome, $userName!');
  }
}

Characteristics

  • Single method: Only build()
  • Cannot change: Properties are final
  • Lightweight: No State object
  • Performance: Efficient for static content

When to Use

  • Static text/images
  • Layout containers
  • Icons and styling
  • Content that doesn't change

Example

dart
class ProfileCard extends StatelessWidget {
  final String name;
  final String email;
  final String avatarUrl;
  
  const ProfileCard({
    required this.name,
    required this.email,
    required this.avatarUrl,
  });
  
  
  Widget build(BuildContext context) {
    return Card(
      child: Column(
        children: [
          CircleAvatar(backgroundImage: NetworkImage(avatarUrl)),
          Text(name, style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
          Text(email, style: TextStyle(color: Colors.grey)),
        ],
      ),
    );
  }
}

StatefulWidget

Definition

A widget that can change over time. Has mutable state managed by a State object.

Structure

dart
class CounterScreen extends StatefulWidget {
  
  _CounterScreenState createState() => _CounterScreenState();
}

class _CounterScreenState extends State<CounterScreen> {
  int _counter = 0; // Mutable state
  
  void _increment() {
    setState(() {
      _counter++;
    });
  }
  
  
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Count: $_counter'),
        ElevatedButton(
          onPressed: _increment,
          child: Text('Increment'),
        ),
      ],
    );
  }
}

Characteristics

  • Two classes: Widget + State
  • Mutable state: Can change via setState()
  • Lifecycle methods: initState(), dispose(), etc.
  • Heavier: More memory and overhead

When to Use

  • Forms and input fields
  • Animations
  • Data fetching/loading states
  • Interactive elements (buttons, checkboxes)
  • Anything that changes over time

Example

dart
class LoginForm extends StatefulWidget {
  
  _LoginFormState createState() => _LoginFormState();
}

class _LoginFormState extends State<LoginForm> {
  final _formKey = GlobalKey<FormState>();
  String _email = '';
  String _password = '';
  bool _isLoading = false;
  
  Future<void> _login() async {
    if (_formKey.currentState!.validate()) {
      setState(() => _isLoading = true);
      
      // Simulate API call
      await Future.delayed(Duration(seconds: 2));
      
      setState(() => _isLoading = false);
    }
  }
  
  
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        children: [
          TextFormField(
            decoration: InputDecoration(labelText: 'Email'),
            onChanged: (value) => _email = value,
          ),
          TextFormField(
            decoration: InputDecoration(labelText: 'Password'),
            obscureText: true,
            onChanged: (value) => _password = value,
          ),
          _isLoading
            ? CircularProgressIndicator()
            : ElevatedButton(
                onPressed: _login,
                child: Text('Login'),
              ),
        ],
      ),
    );
  }
}

Key Differences Explained

1. State Management

StatelessWidget:

dart
// Cannot change this value
final String title = 'Hello';

StatefulWidget:

dart
// Can change via setState()
String title = 'Hello';

void updateTitle() {
  setState(() {
    title = 'Goodbye';
  });
}

2. Rebuild Mechanism

StatelessWidget: Rebuilds only when parent rebuilds

StatefulWidget: Rebuilds when:

  • Parent rebuilds
  • setState() is called
  • Dependencies change

3. Memory Footprint

StatelessWidget:

  • Single object (widget)
  • ~100 bytes

StatefulWidget:

  • Two objects (widget + state)
  • ~200-300 bytes

When to Choose Which

Choose StatelessWidget If:

  • ✅ Data is static
  • ✅ No user interaction
  • ✅ No animations
  • ✅ Display-only content
  • ✅ Performance is critical

Choose StatefulWidget If:

  • ✅ Data changes over time
  • ✅ User input/interaction
  • ✅ Animations
  • ✅ API calls/async operations
  • ✅ Form handling

Best Practices

Rule of Thumb: Start with StatelessWidget. Convert to StatefulWidget only when needed.

dart
// ✅ Good - Use StatelessWidget for static content
class AppTitle extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Text('My App');
  }
}

// ❌ Bad - Unnecessary StatefulWidget
class AppTitle extends StatefulWidget { ... }

// ✅ Good - Use const for better performance
class AppTitle extends StatelessWidget {
  const AppTitle();
  
  
  Widget build(BuildContext context) {
    return const Text('My App');
  }
}

Common Pitfalls

❌ Using StatefulWidget unnecessarily

dart
// Bad - No state changes
class DisplayText extends StatefulWidget { ... }

✅ Use StatelessWidget instead

dart
// Good
class DisplayText extends StatelessWidget { ... }

❌ Forgetting setState()

dart
// Bad - UI won't update
void increment() {
  counter++; // Missing setState()!
}

✅ Always use setState()

dart
// Good
void increment() {
  setState(() {
    counter++;
  });
}

Resources