Posts tagged with “flutter”

Update your flutter app icons with a custom one

1. Prepare Your Icon Image

  • Create a square PNG image (preferably 1024x1024 pixels) for best quality

2. Use the flutter_launcher_icons Package

Add the package to your pubspec.yaml:

flutter pub add flutter_launcher_icons

3. Configure the Icons

Add this configuration to your pubspec.yaml file:

flutter_launcher_icons:
  android: true
  ios: true
  remove_alpha_ios: true
  image_path: "assets/icon/app_icon.png"  # Path to your icon image
  adaptive_icon_background: "#FFFFFF"  # For Android adaptive icons (optional)

4. Run the Package

Run this command in your terminal:

flutter pub get
dart run flutter_launcher_icons

done!

Why We Shouldn't Unconditionally Load Data in `didChangeDependencies

Flutter’s didChangeDependencies lifecycle method is a common source of redundant network requests and data reloads. Based on real-world code examples from a notes app, let’s explore why this happens and how to fix it.


When Does didChangeDependencies Trigger?

didChangeDependencies in Flutter triggers in these scenarios:

  • Immediately after initState()
  • When an InheritedWidget ancestor changes
  • When the widget's dependencies change

In the provided HomePage code:

@override  
void didChangeDependencies() {  
  super.didChangeDependencies();  
  navigateToPage(currentPageNumber); // ❌ Unconditional call  
}  

This causes duplicate API calls every time the event being triggerd.


The Fix: Initialize-Once Flag

class HomePageState extends State<HomePage> {  
  ...
  bool _isInitialized = false; // Add flag  

  @override  
  void didChangeDependencies() {  
    super.didChangeDependencies();  
    if (!_isInitialized) {  
      _isInitialized = true;  
      navigateToPage(currentPageNumber); // ✅ Only first load  
    }  
  }  
  ...
}  

Why This Works

  1. First Load: Initializes data once
  2. Subsequent Route Changes: Skips reload unless explicitly refreshed
  3. Memory Efficiency: Prevents duplicate API calls (evident from the NotesService cache-less implementation)

Key Takeaways

  1. didChangeDependencies isn’t just for initialization
  2. Always guard data-loading logic with flags

[Solution] The argument type 'Consumer' can't be assigned to the parameter type 'PreferredSizeWidget?'.

The error occurs because AppBar expects a widget that implements the PreferredSizeWidget interface, but Consumer<NoteModel> does not directly implement this interface. To solve this, you need to return an AppBar from within the Consumer builder method.

Here’s how you can do it:

Scaffold(
  appBar: PreferredSize(
    preferredSize: Size.fromHeight(kToolbarHeight),
    child: Consumer<NoteModel>(
      builder: (context, noteModel, child) {
        return AppBar(
          title: Text(
            'Your Title',
            style: TextStyle(
              color: noteModel.isPrivate ? Colors.red : Colors.green,
            ),
          ),
        );
      },
    ),
  ),
  body: // Your other widgets,
);

In this approach, I wrapped the Consumer<NoteModel> inside a PreferredSize widget to ensure it adheres to the PreferredSizeWidget interface required by appBar.

This should resolve the error while allowing you to update only the AppBar based on changes in your NoteModel.

Glory to ChatGPT!

Build command for deploying your flutter web app to cloudflare pages

set -x && if cd flutter; then git pull && cd .. ; else git clone https://github.com/flutter/flutter.git; (cd flutter && git fetch --tags && git checkout 3.22.3); fi && ls && flutter/bin/flutter doctor && flutter/bin/flutter clean && flutter/bin/flutter config --enable-web && cp .env.production .env && sed -i "s/VERSION_PLACEHOLDER/`git rev-parse --short HEAD`/" .env && flutter/bin/flutter build web --web-renderer html --base-href="/" --release

Dart `...` Spread Operator: Simplifying Conditional Widget Addition in Flutter

The Dart ... spread operator is a powerful feature that allows you to insert multiple elements from a collection into another collection. This is particularly useful when building Flutter widget trees, as it can make your code more concise and readable.

What is the Spread Operator ...?

The ... operator is used to expand elements of a collection and add them to another collection. For example:

List<int> list1 = [1, 2, 3];
List<int> list2 = [0, ...list1, 4];
print(list2); // Output: [0, 1, 2, 3, 4]

Using the Spread Operator in Flutter Widgets

In Flutter, you can use the ... operator to conditionally add multiple widgets to a widget list, making the code cleaner and more maintainable.

Without the Spread Operator

If you don't use the ... operator, you might end up writing repetitive conditional checks like this:

AppBar(
  title: const Text('Note Details'),
  actions: [
    if (widget.note.userId == UserSession().id)
      IconButton(
        icon: const Icon(Icons.edit),
        onPressed: _enterEditingMode,
      ),
    if (widget.note.userId == UserSession().id)
      IconButton(
        icon: const Icon(Icons.delete),
        onPressed: () async {
          await DialogService.showConfirmDialog(
            context,
            title: 'Delete note',
            text: 'Each note is a story, are you sure you want to delete it?',
            yesCallback: () => _controller.deleteNote(context, widget.note.id),
          );
        },
      ),
  ],
)

This approach involves duplicating the condition check for each widget, making the code verbose and harder to maintain.

With the Spread Operator

Using the ... spread operator, you can simplify the code by grouping the widgets under a single conditional check:

AppBar(
  title: const Text('Note Details'),
  actions: [
    if (widget.note.userId == UserSession().id) ...[
      IconButton(
        icon: const Icon(Icons.edit),
        onPressed: _enterEditingMode,
      ),
      IconButton(
        icon: const Icon(Icons.delete),
        onPressed: () async {
          await DialogService.showConfirmDialog(
            context,
            title: 'Delete note',
            text: 'Each note is a story, are you sure you want to delete it?',
            yesCallback: () => _controller.deleteNote(context, widget.note.id),
          );
        },
      ),
    ],
  ],
)

This method is more concise and only requires a single condition check, reducing redundancy and improving readability.

Benefits of Using the Spread Operator

  1. Reduces Code Duplication: The spread operator allows you to write less code by removing the need for multiple conditional checks.
  2. Improves Readability and Maintainability: With fewer lines of code and clearer structure, your code is easier to read and maintain.
  3. Simplifies Conditional Addition of Multiple Elements: When you need to add multiple elements based on a condition, the spread operator provides a clean and efficient way to do so.