<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Flutter Explained]]></title><description><![CDATA[Welcome to our Flutter Explained Newsletter! Here, you'll find the latest updates, tips, and tricks to help you become a master of the popular mobile app development framework, Flutter.]]></description><link>https://flutterexplained.com</link><image><url>https://substackcdn.com/image/fetch/$s_!c_xz!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F771607a5-8638-498e-a3e9-fc0afe8407c3_1280x1280.png</url><title>Flutter Explained</title><link>https://flutterexplained.com</link></image><generator>Substack</generator><lastBuildDate>Tue, 14 Apr 2026 07:34:36 GMT</lastBuildDate><atom:link href="https://flutterexplained.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Jijo N Johnson]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[jijonjohnson@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[jijonjohnson@substack.com]]></itunes:email><itunes:name><![CDATA[Jijo N Johnson]]></itunes:name></itunes:owner><itunes:author><![CDATA[Jijo N Johnson]]></itunes:author><googleplay:owner><![CDATA[jijonjohnson@substack.com]]></googleplay:owner><googleplay:email><![CDATA[jijonjohnson@substack.com]]></googleplay:email><googleplay:author><![CDATA[Jijo N Johnson]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Flutter UI with the latest chatGPT o1]]></title><description><![CDATA[Discover the incredible capabilities of the ChatGPT o1 model!]]></description><link>https://flutterexplained.com/p/flutter-ui-with-the-latest-chatgpt</link><guid isPermaLink="false">https://flutterexplained.com/p/flutter-ui-with-the-latest-chatgpt</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Mon, 09 Dec 2024 06:42:23 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/ZdnJQRiHXJQ" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-ZdnJQRiHXJQ" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;ZdnJQRiHXJQ&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/ZdnJQRiHXJQ?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>Discover the incredible capabilities of the ChatGPT o1 model! In this video, we put o1 to the test for Flutter UI development and explore just how far it has advanced. Spoiler alert: the progress is truly impressive!</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Updating My VS Code Extension Using ChatGPT's O1 Preview]]></title><description><![CDATA[A Hands-On Guide]]></description><link>https://flutterexplained.com/p/updating-my-vs-code-extension-using</link><guid isPermaLink="false">https://flutterexplained.com/p/updating-my-vs-code-extension-using</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Fri, 11 Oct 2024 08:15:45 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/ZfphQcmfajs" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-ZfphQcmfajs" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;ZfphQcmfajs&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/ZfphQcmfajs?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>In this video, I walk you through the process of enhancing my custom VS Code extension using ChatGPT's O1 Preview. Watch as I add an 'Editable' feature to my extension's status bar buttons, allowing commands to be editable before execution in the terminal.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[VSCode Plugin with ChatGPT O1-Preview ]]></title><description><![CDATA[I created an awesome VSCode plugin for Flutter with chatGPT o1 Preview]]></description><link>https://flutterexplained.com/p/vscode-plugin-with-chatgpt-o1-preview</link><guid isPermaLink="false">https://flutterexplained.com/p/vscode-plugin-with-chatgpt-o1-preview</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Sat, 21 Sep 2024 08:26:50 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/YwyX62Boyrc" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-YwyX62Boyrc" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;YwyX62Boyrc&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/YwyX62Boyrc?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><h1>Custom Command Buttons</h1><p>Add custom buttons to the Visual Studio Code status bar to execute terminal commands with a single click.</p><p>Check it out here: <a href="https://marketplace.visualstudio.com/items?itemName=JijoNJ.custom-command-buttons">VSCode Marketplace</a></p><p>Contribute here: <a href="https://github.com/jijonj/manage_custom_buttons">GitHub Repo</a></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Create Flutter Portfolio Projects for your Resume with ChatGPT 4o for free and Sell it]]></title><description><![CDATA[Create impressive Flutter portfolio projects with the guidance of ChatGPT-4, enhancing your resume with practical, hands-on experience. Learn how to develop, showcase, and even monetize your projects,]]></description><link>https://flutterexplained.com/p/create-flutter-portfolio-projects</link><guid isPermaLink="false">https://flutterexplained.com/p/create-flutter-portfolio-projects</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Tue, 09 Jul 2024 10:03:51 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/ctejb94APQE" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-ctejb94APQE" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;ctejb94APQE&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/ctejb94APQE?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Creating Mason Brick Templates in Flutter Using AI: Step-by-Step Guide]]></title><description><![CDATA[Mason Brick templates using AI tools]]></description><link>https://flutterexplained.com/p/creating-mason-brick-templates-in</link><guid isPermaLink="false">https://flutterexplained.com/p/creating-mason-brick-templates-in</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Mon, 27 May 2024 10:25:30 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/D7dfT4hfDi0" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-D7dfT4hfDi0" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;D7dfT4hfDi0&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/D7dfT4hfDi0?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Flutter Onboarding with Riverpod, Shared Preferences, and GoRouter!]]></title><description><![CDATA[Master Flutter Onboarding: Streamline Your User Experience with Riverpod, Shared Preferences, and GoRouter]]></description><link>https://flutterexplained.com/p/flutter-onboarding-with-riverpod</link><guid isPermaLink="false">https://flutterexplained.com/p/flutter-onboarding-with-riverpod</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Sat, 25 May 2024 15:42:33 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/tdxGg55e6c0" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-tdxGg55e6c0" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;tdxGg55e6c0&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/tdxGg55e6c0?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><h3><strong>Flutter Onboarding with Riverpod, Shared Preferences, and GoRouter</strong></h3><p>In this article, we will explore how to implement an onboarding flow in a Flutter application using GoRouter, Riverpod, and SharedPreferences. This approach helps maintain a cleaner and more modular codebase. We will walk through setting up the necessary dependencies, creating providers with Riverpod, and configuring the router.</p><h4><strong>Prerequisites</strong></h4><p>Ensure you have the following dependencies added to your <code>pubspec.yaml</code>:</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><pre><code>dependencies:
  flutter:
    sdk: flutter
  go_router:
  shared_preferences:
  flutter_riverpod:
  riverpod_annotation:

dev_dependencies:
  build_runner:
  riverpod_generator:
</code></pre><h4><strong>Setting Up Riverpod Provider</strong></h4><p>First, create a Riverpod provider for managing the onboarding state. Use the <code>@riverpod</code> annotation to generate the necessary code.</p><ol><li><p><strong>Create </strong><code>onboarding_provider.dart</code>:</p></li></ol><pre><code>import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:shared_preferences/shared_preferences.dart';

part 'onboarding_provider.g.dart';

@riverpod
class OnboardingNotifier extends _$OnboardingNotifier {
  @override
  bool build() {
    _loadOnboardingStatus();
    return false;
  }

  Future&lt;void&gt; _loadOnboardingStatus() async {
    final prefs = await SharedPreferences.getInstance();
    state = prefs.getBool('onboardingCompleted') ?? false;
  }

  Future&lt;void&gt; completeOnboarding() async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setBool('onboardingCompleted', true);
    state = true;
  }
}
</code></pre><ol start="2"><li><p><strong>Generate the necessary files</strong> by running the build runner:</p></li></ol><pre><code>flutter pub run build_runner build</code></pre><h4><strong>Creating the Router Configuration</strong></h4><p>Next, move the router configuration into a separate <code>app_routes.dart</code> file.</p><ol><li><p><strong>Create </strong><code>app_routes.dart</code>:</p></li></ol><pre><code>import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'onboarding_screen.dart';
import 'home_screen.dart';
import 'onboarding_provider.dart';

class AppRoutes {
  static GoRouter createRouter(WidgetRef ref) {
    final isOnboardingCompleted = ref.watch(onboardingNotifierProvider);

    return GoRouter(
      initialLocation: isOnboardingCompleted ? '/home' : '/onboarding',
      routes: [
        GoRoute(
          path: '/onboarding',
          builder: (context, state) =&gt; OnboardingScreen(),
        ),
        GoRoute(
          path: '/home',
          builder: (context, state) =&gt; HomeScreen(),
        ),
      ],
    );
  }
}
</code></pre><h4><strong>Main Application File</strong></h4><p>Finally, update your main application file to use the router configuration.</p><ol><li><p><strong>Update </strong><code>main.dart</code>:</p></li></ol><pre><code>import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'app_routes.dart';

void main() {
  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final router = AppRoutes.createRouter(ref);

    return MaterialApp.router(
      routerDelegate: router.routerDelegate,
      routeInformationParser: router.routeInformationParser,
      routeInformationProvider: router.routeInformationProvider,
    );
  }
}</code></pre><h4><strong>Onboarding Screen</strong></h4><p>Ensure your onboarding screen interacts correctly with the provider.</p><ol><li><p><strong>Create </strong><code>onboarding_screen.dart</code>:</p></li></ol><pre><code>import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'onboarding_provider.dart';

class OnboardingScreen extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Onboarding'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            await ref.read(onboardingNotifierProvider.notifier).completeOnboarding();
            context.go('/home');
          },
          child: Text('Complete Onboarding'),
        ),
      ),
    );
  }
}
</code></pre><h4><strong>Home Screen</strong></h4><p>Create a simple home screen for the app.</p><ol><li><p><strong>Create </strong><code>home_screen.dart</code>:</p></li></ol><pre><code>import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home'),
      ),
      body: Center(
        child: Text('Welcome to the Home Screen!'),
      ),
    );
  }
}
</code></pre><h3><strong>Conclusion</strong></h3><p>By organizing the router configuration into a separate file (<code>app_routes.dart</code>), you maintain a cleaner and more modular codebase. This approach ensures that your main application file (<code>main.dart</code>) remains concise and focused, improving maintainability and readability. Using Riverpod for state management and SharedPreferences for persistent state ensures a robust and scalable solution for handling onboarding flows in your Flutter application.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Create starter flutter UI for free with ChatGPT 4o]]></title><description><![CDATA[Discover the power of ChatGPT 4o!]]></description><link>https://flutterexplained.com/p/create-starter-flutter-ui-for-free</link><guid isPermaLink="false">https://flutterexplained.com/p/create-starter-flutter-ui-for-free</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Thu, 16 May 2024 10:43:10 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/HTlK6IzMOTc" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-HTlK6IzMOTc" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;HTlK6IzMOTc&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/HTlK6IzMOTc?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>Dive into our latest tutorial where we walk you through crafting a Flutter UI for free with latest and greatest ChatGPT 4o. Perfect for beginners and pros alike.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Episode 4: Image Picker]]></title><description><![CDATA[Season 3: Useful Packages]]></description><link>https://flutterexplained.com/p/episode-4-image-picker</link><guid isPermaLink="false">https://flutterexplained.com/p/episode-4-image-picker</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Sun, 21 Apr 2024 08:27:54 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/_pMZuTi6agE" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-_pMZuTi6agE" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;_pMZuTi6agE&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/_pMZuTi6agE?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><h2><strong>Part 1: Setting Up</strong></h2><p>The first step in using the ImagePicker plugin is to add it to your Flutter project. Open your <code>pubspec.yaml</code> file and add the following line under <code>dependencies</code>:</p><pre><code>dependencies:
  flutter:
    sdk: flutter
  image_picker: ^0.8.4+4
</code></pre><p>After adding this, run <code>flutter pub get</code> in your terminal to install the plugin and its dependencies. This will ensure you have the latest version of the ImagePicker plugin ready to use in your project.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h2><strong>Part 2: Importing the Plugin</strong></h2><p>Now that the plugin is added, let's import it into our Dart file. Add the following import statement at the top of your Dart file:</p><pre><code>import 'package:image_picker/image_picker.dart';</code></pre><p>This import statement allows us to access the ImagePicker functionalities in our code.</p><h2><strong>Part 3: Picking an Image from the Gallery</strong></h2><p>Let's start with the fun part! We'll create a function to pick an image from the gallery. Here's how you can do it:</p><pre><code>Future&lt;void&gt; _pickImageFromGallery() async {
  final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
  if (image != null) {
    setState(() {
      _image = image;
    });
  }
}
</code></pre><p>This function utilizes the <code>ImagePicker</code> to open the gallery, allowing the user to select an image. If an image is selected, it updates the <code>_image</code> variable and triggers a UI update using <code>setState()</code>.</p><h2><strong>Part 4: Picking an Image from the Camera</strong></h2><p>Next, let's write a similar function to pick an image from the camera:</p><pre><code>Future&lt;void&gt; _pickImageFromCamera() async {
  final XFile? image = await _picker.pickImage(source: ImageSource.camera);
  if (image != null) {
    setState(() {
      _image = image;
    });
  }
}</code></pre><p>This function opens the device's camera, allowing the user to capture a new image. Like before, it updates the <code>_image</code> variable if an image is captured.</p><h2><strong>Part 5: Displaying the Image</strong></h2><p>After picking an image, we need to display it in our app. We'll use a widget to achieve this:</p><pre><code>XFile? _image;
final ImagePicker _picker = ImagePicker();

Widget _displayImage() {
  return _image == null
      ? Text('No image selected.')
      : Image.file(File(_image!.path));
}
</code></pre><p>The <code>_displayImage()</code> function checks if an image is selected. If not, it displays a message. If an image is selected, it displays the image using the <code>Image.file()</code> widget.</p><h2><strong>Part 6: Putting It All Together</strong></h2><p>Finally, let's assemble everything into a cohesive user interface:</p><pre><code>@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Image Picker Example'),
    ),
    body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: &lt;Widget&gt;[
          _displayImage(),
          ElevatedButton(
            onPressed: _pickImageFromGallery,
            child: Text('Pick from Gallery'),
          ),
          ElevatedButton(
            onPressed: _pickImageFromCamera,
            child: Text('Pick from Camera'),
          ),
        ],
      ),
    ),
  );
}</code></pre><p>This UI displays the selected image (or a message if no image is selected) and provides buttons to pick images from the gallery and camera.</p><h2><strong>Conclusion</strong></h2><p>And there you have it! You've successfully learned how to integrate the ImagePicker plugin into your Flutter app. With this knowledge, you can easily allow users to pick images from their device's gallery or camera and display them in your app.</p><p>We hope you found this tutorial helpful! If you have any questions or suggestions, please leave them in the comments below. Don't forget to like, share, and subscribe for more Flutter content. Happy coding!</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Episode 3: Shared Preferences Package]]></title><description><![CDATA[Season 3: Useful Packages]]></description><link>https://flutterexplained.com/p/episode-3-shared-preferences-package</link><guid isPermaLink="false">https://flutterexplained.com/p/episode-3-shared-preferences-package</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Sat, 13 Apr 2024 08:24:02 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/ZUjmDPCLyD4" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-ZUjmDPCLyD4" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;ZUjmDPCLyD4&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/ZUjmDPCLyD4?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>In the realm of mobile development, efficiently managing user preferences and data storage locally is crucial. Flutter, with its rich ecosystem, offers a practical solution through the <code>shared_preferences</code> package. This article serves as a comprehensive guide on how to harness this tool, enhancing your Flutter applications by ensuring a personalized and streamlined user experience.</p><h4>Understanding Shared Preferences</h4><p><code>shared_preferences</code> is a Flutter plugin designed for storing key-value pairs on a device's local storage. It's ideal for saving user settings, preferences, and other small data chunks that you want to preserve across sessions. This capability is essential for creating customized user experiences and making your app feel more responsive and intuitive.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h4>Setting Up</h4><p>The integration of <code>shared_preferences</code> starts with adding it as a dependency in your <code>pubspec.yaml</code> file. This simple step involves including the latest version of the package under dependencies:</p><pre><code>dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^latest_version</code></pre><p>After the dependency is added, the next step is importing the package into your Dart file:</p><pre><code>import 'package:shared_preferences/shared_preferences.dart';</code></pre><h4>Saving Data</h4><p>Storing data using <code>shared_preferences</code> is straightforward. For example, to save a username, you would use the <code>setString</code> method. This method is part of a suite that includes <code>setInt</code>, <code>setBool</code>, <code>setDouble</code>, and <code>setStringList</code>, allowing for diverse data storage options:</p><pre><code>Future&lt;void&gt; saveUsername(String username) async {
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  await prefs.setString('username', username);
}</code></pre><h4>Retrieving Data</h4><p>To fetch the stored data, such as the username, use the corresponding getter method. This operation is as simple as calling <code>getString</code> on your <code>SharedPreferences</code> instance. Handling potential <code>null</code> values is crucial to avoid crashes and ensure a smooth user experience:</p><pre><code>Future&lt;String?&gt; getUsername() async {
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  return prefs.getString('username');
}</code></pre><h4>Removing Data</h4><p>To remove data, the <code>remove</code> method is used. This is particularly useful for clearing user settings or preferences when necessary, such as during a logout process:</p><pre><code>Future&lt;void&gt; removeUsername() async {
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  await prefs.remove('username');
}</code></pre><h4>Advanced Usage</h4><p>For more complex data structures, <code>shared_preferences</code> can store serialized objects. By encoding them into JSON, you can save and retrieve structured data. However, it is recommended to use this feature judiciously, as <code>shared_preferences</code> is not designed for storing large datasets:</p><pre><code>import 'dart:convert';

Future&lt;void&gt; saveUser(User user) async {
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  String userJson = jsonEncode(user.toJson());
  await prefs.setString('user', userJson);
}

Future&lt;User?&gt; getUser() async {
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  String? userJson = prefs.getString('user');
  return userJson != null ? User.fromJson(jsonDecode(userJson)) : null;
}</code></pre><h4>Conclusion</h4><p>Mastering <code>shared_preferences</code> in Flutter is a significant step towards building more personalized and efficient applications. This guide provides the foundational knowledge required to implement local storage solutions effectively, making your Flutter apps more robust and user-friendly. Whether you're a beginner or an experienced developer, leveraging this package can greatly enhance your development toolkit.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Unlock Seamless Authentication: Sign in with Google in Flutter App | Supabase Tutorial]]></title><description><![CDATA[Supabase Series]]></description><link>https://flutterexplained.com/p/unlock-seamless-authentication-sign</link><guid isPermaLink="false">https://flutterexplained.com/p/unlock-seamless-authentication-sign</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Fri, 12 Jan 2024 10:25:57 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/CSx7qdyOK-A" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-CSx7qdyOK-A" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;CSx7qdyOK-A&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/CSx7qdyOK-A?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>In this tutorial, we'll guide you through the process of implementing Google Sign-In functionality in your Flutter app without relying on Firebase. Instead, we'll leverage the power of Supabase for a robust and flexible authentication experience.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Episode 1: Launcher Icons package]]></title><description><![CDATA[Season 3: Useful Packages]]></description><link>https://flutterexplained.com/p/episode-1-launcher-icons-package</link><guid isPermaLink="false">https://flutterexplained.com/p/episode-1-launcher-icons-package</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Mon, 04 Dec 2023 14:17:15 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/V43lKF_rEg8" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-V43lKF_rEg8" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;V43lKF_rEg8&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/V43lKF_rEg8?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><h2><strong>Introduction</strong></h2><p>Welcome to the exciting world of Flutter development! In this blog post, we're going to explore how to personalize your Flutter application by setting custom launcher icons using the <code>flutter_launcher_icons</code> package. This tutorial is perfect for both beginners and seasoned Flutter developers looking to add a unique touch to their apps.</p><h2><strong>Why Change Your App's Launcher Icon?</strong></h2><p>When you create a new Flutter project, it comes with the default Flutter icon. While this icon is recognizable, giving your app a unique icon is crucial for branding and user recognition. This is where the <code>flutter_launcher_icons</code> package comes in handy, offering a simple and effective way to customize your app&#8217;s icon for both iOS and Android platforms.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h2><strong>Step 1: Setting up the Package</strong></h2><p>To get started, you need to add the <code>flutter_launcher_icons</code> dependency to your project. Open your <code>pubspec.yaml</code> file and under <code>dev_dependencies</code>, add:</p><pre><code>dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_launcher_icons: latest_version
</code></pre><p>Then, run <code>flutter pub get</code> in your terminal to fetch the latest version of the package.</p><h2><strong>Step 2: Preparing Your Icon</strong></h2><p>Before proceeding, make sure you have a squared icon, ideally 1024x1024 pixels, to ensure high quality across different devices. This icon will represent your app on various platforms.</p><h2><strong>Step 3: Configuring the Icons</strong></h2><p>Next, configure your icons in the <code>pubspec.yaml</code> file. Under the <code>flutter</code> section, add the <code>flutter_icons</code> configuration like so:</p><pre><code>flutter_icons:
  android: true
  ios: true
  image_path: "assets/icon.png"</code></pre><p>This configuration will generate icons for both Android and iOS platforms from the specified <code>image_path</code>.</p><h2><strong>Step 4: Generating the Icons</strong></h2><p>Now for the exciting part! Run the command <code>flutter pub run flutter_launcher_icons:main</code> in your terminal. You'll see logs indicating the successful creation of icons for each platform.</p><h2><strong>Step 5: Verifying the Icons</strong></h2><p>After generating the icons, run your app on both Android and iOS devices or emulators. You should now see your custom launcher icon, showcasing your app's unique identity!</p><h2><strong>Advanced Configuration (Optional)</strong></h2><p>For those interested in more detailed customization, the <code>flutter_launcher_icons</code> package offers advanced configurations. You can specify individual paths for iOS and Android, adapt adaptive icons for Android, and more. Here&#8217;s an example:</p><pre><code>flutter_icons:
  android: "launcher_icon"
  ios: "iosIcon"
  image_path_android: "assets/android_icon.png"
  image_path_ios: "assets/ios_icon.png"
</code></pre><p>Explore the package documentation for a comprehensive understanding of all its capabilities.</p><h2><strong>Conclusion</strong></h2><p>Congratulations! With just a few steps, you&#8217;ve successfully set a custom launcher icon for your Flutter app, giving it a unique and professional look.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[UI Images to Flutter Code with ChatGPT Vision Part-2]]></title><description><![CDATA[UI + ChatGPT = Flutter Code]]></description><link>https://flutterexplained.com/p/ui-images-to-flutter-code-with-chatgpt</link><guid isPermaLink="false">https://flutterexplained.com/p/ui-images-to-flutter-code-with-chatgpt</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Fri, 27 Oct 2023 15:01:36 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/55eb9961-0e74-4cf7-b698-62ef56a88758_1280x720.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-5CjdbckYfVs" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;5CjdbckYfVs&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/5CjdbckYfVs?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>Explore ChatGPT's prowess in converting UI designs to Flutter code in real-time! Dive into this game-changing feature, perfect for accelerating app development.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[UI Images to Flutter Code with new ChatGPT Vision]]></title><description><![CDATA[UI + ChatGPT = Flutter Code]]></description><link>https://flutterexplained.com/p/ui-images-to-flutter-code-with-new</link><guid isPermaLink="false">https://flutterexplained.com/p/ui-images-to-flutter-code-with-new</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Tue, 26 Sep 2023 13:46:32 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/DhuNz1T0dsU" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-DhuNz1T0dsU" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;DhuNz1T0dsU&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/DhuNz1T0dsU?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>Explore ChatGPT's prowess in converting UI designs to Flutter code in real-time! Dive into this game-changing feature, perfect for accelerating app development.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Episode 9: Exploring Dart: Generics]]></title><description><![CDATA[Season 2: Exploring Dart]]></description><link>https://flutterexplained.com/p/episode-9-exploring-dart-generics</link><guid isPermaLink="false">https://flutterexplained.com/p/episode-9-exploring-dart-generics</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Sat, 02 Sep 2023 12:11:11 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/3QMCQ-CdZZw" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-3QMCQ-CdZZw" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;3QMCQ-CdZZw&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/3QMCQ-CdZZw?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>Programming languages evolve, and with them, the tools and techniques they offer. One such powerful tool in modern languages is Generics. They might appear complicated at first glance, but once understood, they can significantly enhance your coding prowess. Let's dive deep into this topic and simplify the world of generics for you.</p><h3><strong>Why Use Generics?</strong></h3><p>The question that might be ringing in your mind is &#8211; why do we need generics? Here's why:</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><ol><li><p><strong>Type Safety</strong>: Generics ensure that you don't mix apples with oranges. It prevents type errors, ensuring that your lists, sets, or other collections only contain the type of items they're supposed to.</p></li></ol><pre><code>var names = &lt;String&gt;[];
names.addAll(['Seth', 'Kathy', 'Lars']);
names.add(42); // This will throw an error.</code></pre><ol><li><p>Here, the error occurs because we declared our list as <code>List&lt;String&gt;</code>, which means it's designed to contain only strings.</p></li><li><p><strong>Better Code Generation</strong>: When the compiler knows the exact type you're working with, it can optimize the generated code, making your program faster and more efficient.</p></li><li><p><strong>Reduce Code Duplication</strong>: Generics allow you to write a single implementation that works with multiple types. Instead of having separate classes or functions for different types, generics allow for flexibility without sacrificing type safety.</p></li></ol><h3><strong>Using Collection Literals with Generics</strong></h3><p>In Dart, you can also specify the type directly when using collection literals.</p><pre><code>var names = &lt;String&gt;['Seth', 'Kathy', 'Lars'];
var uniqueNames = &lt;String&gt;{'Seth', 'Kathy', 'Lars'};
var pages = &lt;String, String&gt;{
  'index.html': 'Homepage',
  'robots.txt': 'Hints for web robots',
  'humans.txt': 'We are people, not machines'
};</code></pre><h3><strong>Parameterized Types with Constructors</strong></h3><p>Generics are not limited to collections. They can be used with constructors as well:</p><pre><code>var nameSet = Set&lt;String&gt;.from(names);
var views = Map&lt;int, View&gt;();</code></pre><h3><strong>Generics and Runtime</strong></h3><p>One of Dart's unique features is that its generics are <strong>reified</strong>. This means they retain their type information during runtime, allowing for more powerful runtime type checks.</p><pre><code>var names = &lt;String&gt;[];
print(names is List&lt;String&gt;); // Outputs true</code></pre><p>Unlike some other languages where generics lose their type at runtime, Dart retains this information, providing an additional layer of safety and flexibility.</p><h3><strong>Restricting the Parameterized Type</strong></h3><p>Generics are flexible, but there are times when you might want to restrict the kind of types a generic class or method can accept. Dart allows you to do this with the <code>extends</code> keyword.</p><pre><code>class Foo&lt;T extends Object&gt; {
  // Only non-nullable types are allowed for T.
}

class Bar&lt;T extends SomeBaseClass&gt; {
  // T must be a subtype of SomeBaseClass or the class itself.
}</code></pre><h3><strong>Using Generic Methods</strong></h3><p>Generics can also be used in methods. They allow a method to operate on different types without sacrificing type safety.</p><pre><code>T first&lt;T&gt;(List&lt;T&gt; ts) {
  // Return the first element of the list ts.
}</code></pre><p>With this function, you can retrieve the first element from a list, irrespective of the list's type.</p><h3><strong>Conclusion</strong></h3><p>Generics, with their angle brackets and type placeholders, can seem intimidating. However, they are a powerful tool designed to make your code safer, more readable, and less redundant. The next time you come across them in code, or the next time you find yourself writing the same function for different types, consider giving generics a try. It might just be the elegant solution you were looking for.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Episode 8: Exploring Dart: Collections]]></title><description><![CDATA[Season 2: Exploring Dart]]></description><link>https://flutterexplained.com/p/episode-8-exploring-dart-collections</link><guid isPermaLink="false">https://flutterexplained.com/p/episode-8-exploring-dart-collections</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Sun, 27 Aug 2023 09:32:24 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/EHVIqaX3yck" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-EHVIqaX3yck" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;EHVIqaX3yck&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/EHVIqaX3yck?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>Among the essential elements that give Dart its power are the data structures known as collections. Whether you're a Dart enthusiast or a novice trying to grasp the basics, understanding Dart collections is fundamental. This article provides a comprehensive insight into Dart&#8217;s Lists, Sets, and Maps.</p><div><hr></div><p><strong>1. Embracing Lists in Dart</strong></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>In many programming languages, arrays are indispensable. Similarly, in Dart, arrays manifest as <code>List</code> objects. More often than not, developers refer to them simply as lists.</p><p>Defining a list is straightforward:</p><pre><code>var list = [1, 2, 3];</code></pre><p>The type is inferred to be <code>List&lt;int&gt;</code>, signifying it will only accommodate integers.</p><p>Interestingly, Dart provides flexibility with list definitions by allowing a trailing comma, which aids in preventing copy-paste errors:</p><pre><code>var list = [
  'Car',
  'Boat',
  'Plane',
];</code></pre><p>Working with lists is intuitive. They follow zero-based indexing, and accessing or modifying their values is done using the subscript operator:</p><pre><code>assert(list[1] == 2);
list[1] = 1;</code></pre><p>For those situations requiring immutability, Dart offers the <code>const</code> keyword:</p><pre><code>var constantList = const [1, 2, 3];</code></pre><div><hr></div><p><strong>2. Navigating Sets</strong></p><p>Sets serve as unordered collections containing unique items. That's right, no duplicates can exist in a Dart set.</p><p>Creating a set is uncomplicated:</p><pre><code>var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'};</code></pre><p>But, if you want to initiate an empty set, employ the curly braces <code>{}</code> with a type argument:</p><pre><code>var names = &lt;String&gt;{};</code></pre><p>Incorporating items into an existing set can be achieved using the <code>add()</code> or <code>addAll()</code> methods:</p><pre><code>var elements = &lt;String&gt;{};
elements.add('fluorine');
elements.addAll(halogens);</code></pre><p>If immutability is the goal, employ <code>const</code>:</p><pre><code>final constantSet = const {
  'fluorine',
  'chlorine',
  'bromine',
  'iodine',
  'astatine',
};</code></pre><div><hr></div><p><strong>3. Mapping with Maps</strong></p><p>Dart&#8217;s <code>Map</code> is an associative collection, pairing keys with corresponding values. Each key is unique, though values can be repetitive.</p><p>Here's how you create a simple map:</p><pre><code>var gifts = {
  'first': 'partridge',
  'second': 'turtledoves',
  'fifth': 'golden rings'
};</code></pre><p>Alternative creation is possible using the Map constructor:</p><pre><code>var nobleGases = Map&lt;int, String&gt;();
nobleGases[2] = 'helium';</code></pre><p>Adding or retrieving key-value pairs is a breeze:</p><pre><code>gifts['fourth'] = 'calling birds'; 
assert(gifts['first'] == 'partridge');</code></pre><p>For constant maps, utilize the <code>const</code> keyword:</p><pre><code>final constantMap = const {
  2: 'helium',
  10: 'neon',
  18: 'argon',
};</code></pre><div><hr></div><p><strong>4. Advanced Operators: The Icing on the Cake</strong></p><p>Dart isn&#8217;t limited to basic operations. It spices up collection manipulations with spread and control-flow operators.</p><p>The spread operator (<code>...</code>) provides an elegant solution for combining collections:</p><pre><code>var list = [1, 2, 3];
var list2 = [0, ...list];</code></pre><p>Control-flow operators like <code>if</code> and <code>for</code> enhance collection-building:</p><pre><code>var nav = ['Home', 'Furniture', 'Plants', if (promoActive) 'Outlet'];</code></pre><div><hr></div><p><strong>In Conclusion</strong></p><p>Dart&#8217;s collections are versatile and efficient. By grasping the essence of Lists, Sets, and Maps, developers can harness Dart's full potential, making data manipulation more streamlined and effective. Dive into Dart and discover the realm of possibilities that await!</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Episode 7: Exploring Dart: Records]]></title><description><![CDATA[Season 2: Exploring Dart]]></description><link>https://flutterexplained.com/p/episode-7-exploring-dart-records</link><guid isPermaLink="false">https://flutterexplained.com/p/episode-7-exploring-dart-records</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Fri, 18 Aug 2023 14:28:03 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/HjCsB4csEzY" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-HjCsB4csEzY" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;HjCsB4csEzY&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/HjCsB4csEzY?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>In the ever-evolving landscape of programming, the introduction of 'Records' stands out as a refreshing innovation. If you're using a programming language version of 3.0 or higher, Records offer a captivating method to structure data. Let's deep dive into understanding this feature.</p><h3><strong>What are Records?</strong></h3><p>At their core, Records are anonymous, immutable aggregate types. They differ from typical collection types such as Lists, Maps, or Sets. Records allow developers to bundle multiple objects into one fixed-size, heterogeneous, and typed entity.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Consider the code snippet:</p><pre><code>var record = ('first', a: 2, b: true, 'last');</code></pre><p>This record neatly wraps different data types into a unified structure. The flexibility is evident &#8211; these records can be stored in variables, passed to/from functions, or even nestled in other data structures like Lists and Maps.</p><h3><strong>Syntax and Structure</strong></h3><p>Records shine in their simplicity and robustness. The expressions used to define a record are essentially comma-separated lists of named or positional fields, all within parentheses. They're also accompanied by type annotations that offer more clarity.</p><p>For example:</p><pre><code>(int, int) swap((int, int) record) {
  var (a, b) = record;
  return (b, a);
}</code></pre><p>This syntax permits a mix of positional and named fields. Curly braces house the named fields, delineating them clearly:</p><pre><code>({int a, bool b}) record;
record = (a: 123, b: true);</code></pre><p>Yet, a word of caution: Records with differently named fields will be considered of different types.</p><h3><strong>Accessing Fields in Records</strong></h3><p>Gaining access to record fields is a straightforward process, thanks to built-in getters. Whether it's a named or a positional field, extraction is a breeze.</p><p>A demonstration:</p><pre><code>var record = ('first', a: 2, b: true, 'last');

print(record.$1); // Outputs 'first'
print(record.a);  // Outputs 2
print(record.b);  // Outputs true
print(record.$2); // Outputs 'last'</code></pre><p>For those desiring even more streamlined access, the concept of Patterns could be explored further.</p><h3><strong>Type, Equality, and the Power of Records</strong></h3><p>The 'shape' of a record&#8212;comprising its field types and names&#8212;uniquely determines its type. Such structural typing fosters intriguing facets like record equality.</p><p>Here's a comparison:</p><pre><code>(int x, int y, int z) point = (1, 2, 3);
(int r, int g, int b) color = (1, 2, 3);

print(point == color); // True is printed</code></pre><p>Notably, the order of named fields doesn't alter equality. In essence, Records autonomously define hashCode and == methods, based on the constitution of their fields.</p><h3><strong>The Beauty of Multiple Returns</strong></h3><p>Records break the shackles when it comes to returning multiple values from functions. Bundling them together provides clarity without compromising type safety.</p><p>Check this out:</p><pre><code>(String, int) userInfo(Map&lt;String, dynamic&gt; json) {
  return (json['name'] as String, json['age'] as int);
}

var (name, age) = userInfo(json);</code></pre><p>This approach outshines alternatives like Lists or Maps, which might forfeit type safety.</p><h3><strong>In Conclusion</strong></h3><p>Records bring a fresh perspective to modern programming, presenting a balanced blend of simplicity, clarity, and power. For developers keen on optimizing their data structures and coding practices, the world of Records awaits exploration.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Episode 6: Exploring Dart: Built-in Types ]]></title><description><![CDATA[Season 2: Exploring Dart]]></description><link>https://flutterexplained.com/p/episode-6-exploring-dart-built-in</link><guid isPermaLink="false">https://flutterexplained.com/p/episode-6-exploring-dart-built-in</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Wed, 16 Aug 2023 16:41:49 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/S7XkTGUB3r0" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-S7XkTGUB3r0" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;S7XkTGUB3r0&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/S7XkTGUB3r0?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p><strong>Diving Deep into Dart's Built-in Types</strong></p><p>Dart, a client-optimized language for building fast apps on any platform, provides a plethora of built-in types that make app development easier, more efficient, and robust. In this article, we'll unravel the rich tapestry of built-in types in Dart, shedding light on the syntax and the unique features they bring to the table.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h2><strong>1. Overview of Built-in Types</strong></h2><p>Dart has a special affinity for the following types:</p><ul><li><p><strong>Numbers</strong>: int, double</p></li><li><p><strong>Strings</strong>: String</p></li><li><p><strong>Booleans</strong>: bool</p></li><li><p><strong>Records</strong>: (value1, value2)</p></li><li><p><strong>Lists</strong>: List (also termed as arrays)</p></li><li><p><strong>Sets</strong>: Set</p></li><li><p><strong>Maps</strong>: Map</p></li><li><p><strong>Runes</strong>: Runes</p></li><li><p><strong>Symbols</strong>: Symbol</p></li><li><p><strong>Null</strong>: Null</p></li></ul><p>Literals make it possible to create objects directly. For instance, 'Hello, World!' is a string literal, while true represents a boolean literal. But, Dart goes beyond just literals. Almost every variable in Dart is an object instance, and many of these types come with built-in constructors. For example, the Map() constructor lets you craft a map.</p><p>Special roles in the Dart ecosystem are also played by:</p><ul><li><p>Object: The universal superclass, barring Null.</p></li><li><p>Enum: Paves the way for enumerations.</p></li><li><p>Future &amp; Stream: The cornerstones of asynchrony.</p></li><li><p>Iterable: Essential for <code>for-in</code> loops and generator functions.</p></li><li><p>Never: Represents expressions that will never fully evaluate.</p></li><li><p>dynamic: When you need to turn off static checking.</p></li><li><p>void: The black hole type &#8211; values that get sucked in are never used.</p></li></ul><h2><strong>2. Cracking the Code on Numbers</strong></h2><p>Dart categorizes numbers into:</p><ul><li><p><strong>int</strong>: Integer values can span up to 64 bits, influenced by the platform.</p></li><li><p><strong>double</strong>: 64-bit floating-point numbers, compliant with the IEEE 754 standard.</p></li></ul><p>Both of these are under the umbrella of <code>num</code>, which supports basic arithmetic operations. The dart:math library comes to your aid if you need advanced operations.</p><p>A unique feature is how Dart handles integer and double conversions. An integer is auto-converted to a double when required. Also, you can switch between string representations of numbers and their actual values seamlessly.</p><pre><code>var one = int.parse('1'); 
String piAsString = 3.14159.toStringAsFixed(2);</code></pre><h2><strong>3. Weaving Words with Strings</strong></h2><p>Strings in Dart hold sequences of UTF-16 code units. You can weave strings using single or double quotes, escape sequences, and even use string interpolation to insert an expression's value directly into a string.</p><p>String concatenation in Dart is intuitive and versatile:</p><pre><code>var combined = 'String interpolation in ' + 'Dart is powerful!';</code></pre><p>For multi-line strings, Dart provides triple quotes. Furthermore, "raw" strings, prefixed with <code>r</code>, consider every character as a literal, turning escape sequences inert.</p><h2><strong>4. Binary Logic with Booleans</strong></h2><p>In Dart, booleans are either true or false. Dart values type safety, ensuring developers can't mistakenly pass non-boolean values where boolean values are expected.</p><h2><strong>5. A Symphony of Symbols and Runes</strong></h2><p>Runes open the world of Unicode to developers. Unicode assigns unique numeric values to characters from all global writing systems. In Dart, runes let you access a string&#8217;s Unicode points directly.</p><p>If you're intrigued by emojis like &#128518; or special characters like &#9829;, they have Unicode representations like <code>\u{1f606}</code> and <code>\u2665</code>, respectively. For intricate manipulations involving Unicode characters, Dart provides the <code>characters</code> package.</p><p>Symbols, on the other hand, are crucial when referring to identifiers by name, especially in the face of minification. With symbol literals, represented by <code>#</code> followed by the identifier, Dart provides a direct reference to an identifier, immune to name changes.</p><h2><strong>Conclusion</strong></h2><p>Dart&#8217;s built-in types not only provide robustness to the language but also ensure that developers can write concise and efficient code. From numbers to strings, and symbols to runes, Dart caters to every need, laying the foundation for fast, platform-agnostic app development.</p><p>Whether you're new to Dart or brushing up on the basics, understanding these built-in types can empower you to craft more optimized, readable, and efficient applications. Happy coding!</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Episode 5: Exploring Dart: Metadata, Libraries and Imports in Dart]]></title><description><![CDATA[Season 2: Exploring Dart]]></description><link>https://flutterexplained.com/p/episode-5-exploring-dart-metadata</link><guid isPermaLink="false">https://flutterexplained.com/p/episode-5-exploring-dart-metadata</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Tue, 15 Aug 2023 06:34:28 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/OootlhPEa3I" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-OootlhPEa3I" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;OootlhPEa3I&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/OootlhPEa3I?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><h3><strong>Metadata, Libraries, and Imports in Dart</strong></h3><p>Programming languages are built with certain constructs that help developers write clean, maintainable, and modular code. Dart, the language behind the popular Flutter framework, is no exception. In this article, we'll explore three core features of Dart: Metadata, Libraries, and Imports.</p><h4><strong>Metadata in Dart</strong></h4><p>Metadata in Dart serves as a tool to give additional context or information about parts of your code. At its core, a metadata annotation begins with the character <code>@</code>, followed either by a reference to a compile-time constant or a call to a constant constructor.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Common annotations you might come across in Dart include:</p><ul><li><p><code>@Deprecated</code>: Indicates that a certain code element is deprecated and shouldn't be used.</p></li><li><p><code>@override</code>: Signifies that the annotated method is intended to override a superclass method.</p></li></ul><p>Here's an example using the <code>@Deprecated</code> annotation:</p><pre><code>class Television {
  /// Use [turnOn] to turn the power on instead.
  @Deprecated('Use turnOn instead')
  void activate() {
    turnOn();
  }

  void turnOn() {/*...*/}
}</code></pre><p>Beyond these standard annotations, Dart allows developers to define custom metadata annotations. For instance:</p><pre><code>class Todo {
  final String who;
  final String what;

  const Todo(this.who, this.what);
}

@Todo('Dash', 'Implement this function')
void doSomething() {
  print('Do something');
}</code></pre><p>In the example above, the custom <code>@Todo</code> annotation provides additional context about who is responsible for the function and what their task is.</p><h4><strong>Libraries and Imports</strong></h4><p>Dart&#8217;s <code>import</code> and <code>library</code> directives play an instrumental role in aiding developers to craft a modular and shareable code base. More than mere APIs, libraries in Dart are also a unit of privacy. Identifiers that start with an underscore (_) are visible only inside the library. This unique feature ensures that every Dart file (and its parts) acts as a standalone library.</p><p>Dart provides a plethora of built-in libraries. For instance, Dart web applications typically utilize the <code>dart:html</code> library:</p><pre><code>import 'dart:html';</code></pre><p>For libraries not part of the Dart core, the <code>package:</code> scheme is used. This denotes libraries provided by a package manager like the pub tool:</p><pre><code>import 'package:test/test.dart';</code></pre><p>When two libraries have conflicting identifiers, Dart provides the flexibility to specify a prefix for one or both of the libraries:</p><pre><code>import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;

// Uses Element from lib1.
Element element1 = Element();

// Uses Element from lib2.
lib2.Element element2 = lib2.Element();</code></pre><p>Dart also offers the power to selectively import parts of a library using <code>show</code> and <code>hide</code>:</p><pre><code>// Import only foo.
import 'package:lib1/lib1.dart' show foo;

// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;</code></pre><p>For more advanced scenarios, Dart supports lazy loading (or deferred loading) of libraries. This mechanism allows a web application to load a library on demand:</p><pre><code>import 'package:greetings/hello.dart' deferred as hello;

Future&lt;void&gt; greet() async {
  await hello.loadLibrary();
  hello.printGreeting();
}</code></pre><h4><strong>In Conclusion</strong></h4><p>Dart&#8217;s Metadata, Libraries, and Import features are vital for developers who want to write clean, organized, and modular code. Whether you're diving into Dart for web development or building fluttering Flutter apps, mastering these concepts will undoubtedly elevate your Dart development journey.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Episode 4: Exploring Dart: Comments ]]></title><description><![CDATA[Season 2: Exploring Dart]]></description><link>https://flutterexplained.com/p/episode-3-exploring-dart-comments</link><guid isPermaLink="false">https://flutterexplained.com/p/episode-3-exploring-dart-comments</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Tue, 08 Aug 2023 15:24:20 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/2JvN8jlAjKc" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-2JvN8jlAjKc" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;2JvN8jlAjKc&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/2JvN8jlAjKc?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>Dart, an object-oriented programming language, is seeing a surge in popularity due to its efficiency, conciseness, and ease of learning. As with many languages, comments are a fundamental part of coding in Dart. In this article, we'll explore the various types of comments in Dart: single-line comments, multi-line comments, and documentation comments.</p><h2><strong>Single-line Comments</strong></h2><p>A single-line comment in Dart begins with two forward slashes <code>//</code>. Everything that comes after these slashes, on the same line, is ignored by the Dart compiler.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Example:</p><pre><code>void main() {
  // TODO: refactor into an AbstractLlamaGreetingFactory?
  print('Welcome to my Llama farm!');
}</code></pre><p>Here, the single-line comment is a handy reminder to refactor a piece of code in the future. This comment doesn't interfere with the execution of the code, and the program will print 'Welcome to my Llama farm!' when run.</p><h2><strong>Multi-line Comments</strong></h2><p>For situations where a comment spans several lines, Dart provides multi-line comments that begin with <code>/*</code> and end with <code>*/</code>. Every character between these symbols is ignored by the Dart compiler. This is often used for temporarily disabling chunks of code or adding extended descriptions.</p><p>Example:</p><pre><code>void main() {
  /*
   * This is a lot of work. Consider raising chickens.
   * 
   Llama larry = Llama();
   larry.feed();
   larry.exercise();
   larry.clean();
   */
}</code></pre><p>The block of code inside the multi-line comment is disregarded by the compiler, making it easy to comment out large parts of code for testing or debugging.</p><h2><strong>Documentation Comments</strong></h2><p>Dart takes commenting a step further with documentation comments, which can be used to generate documentation for your classes, methods, and variables. These comments begin with <code>///</code> for single-line, or <code>/**</code> for multi-line comments. They can also include Markdown formatting.</p><p>Example:</p><pre><code>/// A domesticated South American camelid (Lama glama).
///
/// Andean cultures have used llamas as meat and pack
/// animals since pre-Hispanic times.
///
/// Just like any other animal, llamas need to eat,
/// so don't forget to [feed] them some [Food].
class Llama {
  String? name;

  /// Feeds your llama [food].
  ///
  /// The typical llama eats one bale of hay per week.
  void feed(Food food) {
    // ...
  }

  /// Exercises your llama with an [activity] for
  /// [timeLimit] minutes.
  void exercise(Activity activity, int timeLimit) {
    // ...
  }
}</code></pre><p>Documentation comments enable developers to add rich, linked documentation to their code. Here, <code>[feed]</code> will become a link to the documentation for the <code>feed</code> method, and <code>[Food]</code> a link to the <code>Food</code> class in the generated documentation.</p><h2><strong>Conclusion</strong></h2><p>Comments in Dart provide a versatile and robust way to make code more readable, maintainable, and understandable. From single-line reminders to multi-line explanations to full-fledged documentation, Dart supports it all.</p><p>Remember, comments are not just for your future self; they are essential for anyone else who reads your code. Good commenting practice helps in team collaboration, easy debugging, and code quality.</p><p>Dive into Dart and make the best use of these commenting capabilities. Whether you're building a simple script or a complex application, comments will be your allies in producing clean, clear, and efficient code. Happy coding!</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Episode 3: Exploring Dart: Operators]]></title><description><![CDATA[Season 2: Exploring Dart #dartforbeginners]]></description><link>https://flutterexplained.com/p/episode-3-exploring-dart-operators</link><guid isPermaLink="false">https://flutterexplained.com/p/episode-3-exploring-dart-operators</guid><dc:creator><![CDATA[Jijo N Johnson]]></dc:creator><pubDate>Mon, 07 Aug 2023 16:19:55 GMT</pubDate><enclosure url="https://substackcdn.com/image/youtube/w_728,c_limit/0xUSDBYv7i8" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div id="youtube2-0xUSDBYv7i8" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;0xUSDBYv7i8&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/0xUSDBYv7i8?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>Dart, a powerful programming language, brings to the table a plethora of operators that serve different purposes. This article aims to explore these operators, delineating their associativity and precedence, and providing practical examples of their use.</p><h2><strong>Overview</strong></h2><p>Dart's operators can be grouped into various categories including arithmetic, relational, logical, bitwise, shift, conditional, cascade, and more. Let's delve into each of these categories to understand their functionality.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h3><strong>1. Unary Operators</strong></h3><p>These are operators that act on a single operand. They can be divided into:</p><h4>a. Unary Postfix:</h4><pre><code>expr++    expr--    ()    []    ?[]    .    ?.    !</code></pre><p>Associativity: None</p><h4>b. Unary Prefix:</h4><pre><code>-expr    !expr    ~expr    ++expr    --expr      await expr</code></pre><p>Associativity: None</p><h3><strong>2. Arithmetic Operators</strong></h3><p>These operators are used for mathematical operations. They include:</p><h4>a. Multiplicative:</h4><pre><code>*    /    %    ~/</code></pre><p>Associativity: Left</p><h4>b. Additive:</h4><pre><code>+    -</code></pre><p>Associativity: Left</p><p>Here's an example of arithmetic operators in action:</p><pre><code>assert(2 + 3 == 5);
assert(2 * 3 == 6);</code></pre><h3><strong>3. Shift Operators</strong></h3><p>These operators shift the bits of their operand.</p><pre><code>&lt;&lt;    &gt;&gt;    &gt;&gt;&gt;</code></pre><p>Associativity: Left</p><h3><strong>4. Bitwise Operators</strong></h3><p>Used to manipulate individual bits:</p><pre><code>&amp;    ^    |</code></pre><p>Associativity: Left</p><h3><strong>5. Relational and Type Test Operators</strong></h3><p>For comparison and type checks:</p><pre><code>&gt;=    &gt;    &lt;=    &lt;    as    is    is!</code></pre><p>Associativity: None</p><h3><strong>6. Equality Operators</strong></h3><p>These are for equality checks:</p><pre><code>==    !=</code></pre><p>Associativity: None</p><h3><strong>7. Logical Operators</strong></h3><p>Logical AND and OR:</p><pre><code>&amp;&amp;    ||</code></pre><p>Associativity: Left</p><h3><strong>8. Conditional Operators</strong></h3><p>These include the standard ternary operator:</p><pre><code>expr1 ? expr2 : expr3</code></pre><p>Associativity: Right</p><h3><strong>9. Cascade Notation</strong></h3><p>A way to make a sequence of operations on the same object:</p><pre><code>..    ?..</code></pre><p>Associativity: Left</p><h3><strong>10. Assignment Operators</strong></h3><p>These include standard and compound assignments:</p><pre><code>=    *=    /=    +=    -=    &amp;=    ^=    etc.</code></pre><p>Associativity: Right</p><h2><strong>Special Considerations</strong></h2><p>The above table should be used as a guide, but for authoritative behavior, consult Dart's language specification.</p><h3><strong>Precedence Example</strong></h3><p>In Dart, higher-precedence operators execute before lower-precedence ones:</p><pre><code>if (n % i == 0 &amp;&amp; d % i == 0) ...</code></pre><h3><strong>Type Test Operators</strong></h3><p><code>as</code>, <code>is</code>, and <code>is!</code> operators are handy for checking types:</p><pre><code>if (employee is Person) {
  employee.firstName = 'Bob';
}</code></pre><h3><strong>Cascade Notation</strong></h3><p>Cascades allow a sequence of operations on the same object:</p><pre><code>var paint = Paint()
  ..color = Colors.black
  ..strokeCap = StrokeCap.round;</code></pre><h3><strong>Other Operators</strong></h3><p>Other operators like function application <code>()</code>, subscript access <code>[]</code>, conditional subscript access <code>?[]</code>, and member access <code>.</code> are essential as well.</p><h2><strong>Conclusion</strong></h2><p>Dart offers an extensive set of operators, each with a distinct purpose. The above guide is intended to serve as a comprehensive reference for Dart developers seeking to understand and implement these operators effectively.</p><p>By familiarizing themselves with the syntax and usage of these operators, developers can write concise and efficient code. The Dart language specification should be referred to for the most authoritative and detailed information on this subject.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://flutterexplained.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Flutter Explained! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item></channel></rss>