<?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"><channel><title><![CDATA[Untitled Publication]]></title><description><![CDATA[Untitled Publication]]></description><link>https://truongnn.me</link><generator>RSS for Node</generator><lastBuildDate>Wed, 16 Sep 2026 03:09:52 GMT</lastBuildDate><atom:link href="https://truongnn.me/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Dart's Analyzer missed required parameters]]></title><description><![CDATA[When working with Dart, developers expect the compiler and analyzer to catch null-related issues at compile time. However, there are cases where the Dart analyzer can miss nullability checks, allowing code that may compile successfully but throw erro...]]></description><link>https://truongnn.me/darts-analyzer-missed-required-parameters</link><guid isPermaLink="true">https://truongnn.me/darts-analyzer-missed-required-parameters</guid><category><![CDATA[Null Safety]]></category><dc:creator><![CDATA[Truong Nguyen]]></dc:creator><pubDate>Sun, 03 Nov 2024 14:41:51 GMT</pubDate><content:encoded><![CDATA[<p>When working with Dart, developers expect the compiler and analyzer to catch null-related issues at compile time. However, there are cases where the Dart analyzer can miss nullability checks, allowing code that may compile successfully but throw errors at runtime.</p>
<p>Let's look at a code snippet that compiles but fails at runtime:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EndPoint</span> </span>{
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> path;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">String</span> method;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; headers;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; queryParameters;
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt; body;

  EndPoint({
    <span class="hljs-keyword">this</span>.path,
    <span class="hljs-keyword">this</span>.method,
    <span class="hljs-keyword">this</span>.headers,
    <span class="hljs-keyword">this</span>.queryParameters,
    <span class="hljs-keyword">this</span>.body,
  });

  <span class="hljs-keyword">void</span> execute() {
    <span class="hljs-built_in">print</span>(<span class="hljs-string">'Executing endpoint'</span>);
  }
}
</code></pre>
<h1 id="heading-the-problem">The problem</h1>
<p>In this class, <code>headers</code>, <code>queryParameters</code>, and <code>body</code> are declared as non-nullable <code>Map&lt;String, dynamic&gt;</code> fields. But they don’t have default values or required markers, they implicitly default to <code>null</code>. Dart’s analyzer doesn’t catch this issue during compilation, which leads to the following runtime error:</p>
<pre><code class="lang-dart">Error: The parameter <span class="hljs-string">'headers'</span> can<span class="hljs-string">'t have a value of '</span><span class="hljs-keyword">null</span><span class="hljs-string">' because of its type '</span><span class="hljs-built_in">Map</span>&lt;<span class="hljs-built_in">String</span>, <span class="hljs-built_in">dynamic</span>&gt;<span class="hljs-string">', but the implicit default value is '</span><span class="hljs-keyword">null</span><span class="hljs-string">'.</span>
</code></pre>
<p>A solution would be to explicitly declare these parameters as required, as shown below:</p>
<p>A solution would be explicitly declare these parameters as required:</p>
<pre><code class="lang-dart">EndPoint({
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.path,
    <span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.method,
    <span class="hljs-keyword">this</span>.headers = <span class="hljs-keyword">const</span> {},
    <span class="hljs-keyword">this</span>.queryParameters = <span class="hljs-keyword">const</span> {},
    <span class="hljs-keyword">this</span>.body = <span class="hljs-keyword">const</span> {},
});
</code></pre>
<p>The analyzer may not catch every null-safety issue.</p>
]]></content:encoded></item><item><title><![CDATA[Creating Scalable and Maintainable Collection Managers in Dart]]></title><description><![CDATA[Scenario
Suppose we are building a social media application where we need to manage user profiles. The profiles contain attributes like id, name, and age. Below, I demonstrate how using the UserProfiles class makes the code cleaner, reusable, and eas...]]></description><link>https://truongnn.me/creating-scalable-and-maintainable-collection-managers-in-dart</link><guid isPermaLink="true">https://truongnn.me/creating-scalable-and-maintainable-collection-managers-in-dart</guid><dc:creator><![CDATA[Truong Nguyen]]></dc:creator><pubDate>Wed, 16 Oct 2024 22:53:02 GMT</pubDate><content:encoded><![CDATA[<h4 id="heading-scenario">Scenario</h4>
<p>Suppose we are building a social media application where we need to manage user profiles. The profiles contain attributes like <code>id</code>, <code>name</code>, and <code>age</code>. Below, I demonstrate how using the <code>UserProfiles</code> class makes the code cleaner, reusable, and easier to maintain compared to handling it manually without this utility class.</p>
<h4 id="heading-without-userprofiles-class">Without <code>UserProfiles</code> Class</h4>
<p>Let's consider a scenario where we need to:</p>
<ol>
<li><p>Add profiles.</p>
</li>
<li><p>Update a user's name by their <code>id</code>.</p>
</li>
<li><p>Filter profiles by age.</p>
</li>
<li><p>Remove duplicate profiles based on <code>id</code>.</p>
</li>
</ol>
<h5 id="heading-code-without-userprofiles">Code without <code>UserProfiles</code>:</h5>
<pre><code class="lang-plaintext">dartCopy codeimport 'user_profile.dart';

List&lt;UserProfile&gt; profiles = [];

// Add a new profile
profiles.add(UserProfile(id: '1', name: 'Alice', age: 25));
profiles.add(UserProfile(id: '2', name: 'Bob', age: 30));

// Update user profile by id
String idToUpdate = '1';
for (int i = 0; i &lt; profiles.length; i++) {
  if (profiles[i].id == idToUpdate) {
    profiles[i] = profiles[i].copyWith(name: 'Alice Updated');
  }
}

// Filter profiles by age &gt; 26
List&lt;UserProfile&gt; filteredProfiles = profiles.where((profile) =&gt; profile.age &gt; 26).toList();

// Remove duplicate profiles by id
final seen = &lt;String&gt;{};
profiles = profiles.where((profile) =&gt; seen.add(profile.id)).toList();
</code></pre>
<h5 id="heading-problems-with-this-approach">Problems with This Approach:</h5>
<ol>
<li><p><strong>Boilerplate Code</strong>: We need to write repetitive code to iterate over the list whenever we want to perform operations like update, filter, or remove duplicates.</p>
</li>
<li><p><strong>Lack of Reusability</strong>: Each time we need to add similar functionality (e.g., finding a profile or updating it), we have to manually write the code, which is error-prone.</p>
</li>
<li><p><strong>Complexity</strong>: As the application grows, managing user profiles will require more such operations, increasing the complexity of maintaining the code.</p>
</li>
</ol>
<h4 id="heading-with-userprofiles-class">With <code>UserProfiles</code> Class</h4>
<p>Now, let's use the <code>UserProfiles</code> class to perform the same operations.</p>
<h5 id="heading-code-with-userprofiles">Code with <code>UserProfiles</code>:</h5>
<pre><code class="lang-plaintext">dartCopy codeimport 'user_profile.dart';

void main() {
  // Initialize an empty collection of user profiles
  UserProfiles&lt;UserProfile&gt; userProfiles = UserProfiles&lt;UserProfile&gt;.empty();

  // Add profiles
  userProfiles.addProfile(UserProfile(id: '1', name: 'Alice', age: 25));
  userProfiles.addProfile(UserProfile(id: '2', name: 'Bob', age: 30));

  // Update a user profile by id
  userProfiles.updateProfileWithId('1', (profile) =&gt; profile.copyWith(name: 'Alice Updated'));

  // Filter profiles by age &gt; 26
  UserProfiles&lt;UserProfile&gt; filteredProfiles = userProfiles.filter((profile) =&gt; profile.age &gt; 26);

  // Remove duplicate profiles by id
  userProfiles.removeDuplicates((profile) =&gt; profile.id);
}
</code></pre>
<h5 id="heading-advantages-of-this-approach">Advantages of This Approach:</h5>
<ol>
<li><p><strong>Cleaner Code</strong>: The operations are clearly defined, and the usage of methods like <code>updateProfileWithId</code> or <code>removeDuplicates</code> makes the code more readable and easier to understand.</p>
</li>
<li><p><strong>Reusable Methods</strong>: The <code>UserProfiles</code> class encapsulates common list operations, promoting reusability. We can call <code>addProfile</code>, <code>filter</code>, or <code>removeDuplicates</code> as needed without rewriting the logic.</p>
</li>
<li><p><strong>Extensibility</strong>: If you need new methods, like sorting profiles or finding the first element of a specific type, you can add them directly in the <code>UserProfiles</code> class. This approach keeps your logic encapsulated in one place.</p>
</li>
<li><p><strong>Immutability</strong>: The <code>addedProfile</code>, <code>addedAllProfiles</code>, and similar methods return new instances, which is useful for keeping data immutable—important in state management (e.g., when using Bloc or Redux in Flutter).</p>
</li>
</ol>
<h3 id="heading-summary">Summary</h3>
<p>The <code>UserProfiles</code> class provides a clean, reusable, and easy-to-maintain approach for managing collections of user profiles. Instead of writing repetitive and error-prone boilerplate code, you can rely on a well-defined API that allows for common operations like adding, updating, filtering, and removing duplicates. This is especially beneficial for larger projects or when dealing with complex data models.</p>
]]></content:encoded></item><item><title><![CDATA[[Tip] Cannot see pod command after install cocoapods]]></title><description><![CDATA[gem uninstall cocoapods
brew reinstall cocoapods
# check version
pod --version]]></description><link>https://truongnn.me/tip-cannot-see-pod-command-after-install-cocoapods</link><guid isPermaLink="true">https://truongnn.me/tip-cannot-see-pod-command-after-install-cocoapods</guid><category><![CDATA[tips]]></category><dc:creator><![CDATA[Truong Nguyen]]></dc:creator><pubDate>Sun, 21 Apr 2024 06:01:46 GMT</pubDate><content:encoded><![CDATA[<pre><code class="lang-swift">gem uninstall cocoapods
brew reinstall cocoapods
# check version
pod --version
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Updating the PATH Variable in the Shell]]></title><description><![CDATA[Introduction
The PATH environment variable is a critical component in Unix-like operating systems, including Linux and macOS. It helps the shell identify where to find executable files when commands are entered. Updating the PATH variable allows user...]]></description><link>https://truongnn.me/updating-the-path-variable-in-the-shell</link><guid isPermaLink="true">https://truongnn.me/updating-the-path-variable-in-the-shell</guid><category><![CDATA[Basic linux commands]]></category><category><![CDATA[basic guide]]></category><category><![CDATA[shell]]></category><dc:creator><![CDATA[Truong Nguyen]]></dc:creator><pubDate>Sun, 21 Apr 2024 04:35:59 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-introduction"><strong>Introduction</strong></h2>
<p>The <code>PATH</code> environment variable is a critical component in Unix-like operating systems, including Linux and macOS. It helps the shell identify where to find executable files when commands are entered. Updating the <code>PATH</code> variable allows users to run software from any directory without specifying the full path to its executable.</p>
<h2 id="heading-example-adding-the-flutter-sdk-to-the-path"><strong>Example: Adding the Flutter SDK to the</strong> <code>PATH</code></h2>
<p>Consider you have installed the Flutter SDK to <code>~/Documents/development/flutter</code>. To use the Flutter commands from anywhere in your terminal, you need to add the Flutter SDK's <code>bin</code> directory to your <code>PATH</code>.</p>
<p>For Bash users, edit <code>~/.bashrc</code>.</p>
<p>For Zsh users, edit <code>~/.zshrc</code>.</p>
<p>Add the following line at the end of your configuration file:</p>
<pre><code class="lang-swift">export <span class="hljs-type">PATH</span>=<span class="hljs-string">"$PATH:$HOME/Documents/development/flutter/bin"</span>
</code></pre>
<p>Apply the changes</p>
<pre><code class="lang-swift">source ~/.bashrc  # <span class="hljs-type">If</span> using <span class="hljs-type">Bash</span>
source ~/.zshrc   # <span class="hljs-type">If</span> using <span class="hljs-type">Zsh</span>
</code></pre>
<p>Verify the Update</p>
<pre><code class="lang-swift">echo $<span class="hljs-type">PATH</span>
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Understanding Shells: A Basic Guide]]></title><description><![CDATA[Introduction
In computing, a shell is a user interface that provides access to various services of an operating system's kernel. Shells can be either graphical or command-line based, with the latter being prevalent in Unix-like systems, including mac...]]></description><link>https://truongnn.me/understanding-shells-a-basic-guide</link><guid isPermaLink="true">https://truongnn.me/understanding-shells-a-basic-guide</guid><category><![CDATA[basic guide]]></category><category><![CDATA[shell]]></category><category><![CDATA[Basic linux commands]]></category><dc:creator><![CDATA[Truong Nguyen]]></dc:creator><pubDate>Thu, 18 Apr 2024 08:03:53 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-introduction"><strong>Introduction</strong></h2>
<p>In computing, a shell is a user interface that provides access to various services of an operating system's kernel. Shells can be either graphical or command-line based, with the latter being prevalent in Unix-like systems, including macOS and Linux.</p>
<h2 id="heading-list-of-common-shells"><strong>List of Common Shells</strong></h2>
<p>Shells come in various forms and serve multiple purposes, from simple command execution to full scripting capabilities. Here are some of the most commonly used shells:</p>
<ol>
<li><p><strong>Bash (Bourne Again Shell)</strong> - The most widespread shell on Linux systems and older macOS versions. It is an enhanced version of the original Bourne shell (<code>sh</code>).</p>
</li>
<li><p><strong>Zsh (Z Shell)</strong> - Known for its improvements over Bash, offering better user customization, completion features, and scripting facilities. Zsh is the default shell in newer versions of macOS.</p>
</li>
</ol>
<h2 id="heading-how-to-check-your-shell-on-macos"><strong>How to Check Your Shell on macOS</strong></h2>
<h3 id="heading-using-terminal-commands"><strong>Using Terminal Commands</strong></h3>
<ul>
<li><p><strong>Step 1</strong>: Open your Terminal application. This can typically be found in the Utilities folder under Applications.</p>
</li>
<li><p><strong>Step 2</strong>: To find out the default shell, type the following command and press Enter:</p>
<pre><code class="lang-swift">  echo $<span class="hljs-type">SHELL</span>
</code></pre>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>  Knowing how to check and change your default shell is a valuable skill in the Unix-like operating system domain.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Simplifying Array Initialization in Swift with Array(repeating:)]]></title><description><![CDATA[When developing in Swift, a common requirement is to initialize an array where multiple elements share the same initial value. This scenario can arise in various contexts, such as setting up default configurations, pre-filling data structures, or ini...]]></description><link>https://truongnn.me/simplifying-array-initialization-in-swift-with-arrayrepeating</link><guid isPermaLink="true">https://truongnn.me/simplifying-array-initialization-in-swift-with-arrayrepeating</guid><category><![CDATA[Swift]]></category><category><![CDATA[swifttips]]></category><category><![CDATA[Tips for Developers]]></category><dc:creator><![CDATA[Truong Nguyen]]></dc:creator><pubDate>Sun, 07 Apr 2024 16:05:13 GMT</pubDate><content:encoded><![CDATA[<p>When developing in Swift, a common requirement is to initialize an array where multiple elements share the same initial value. This scenario can arise in various contexts, such as setting up default configurations, pre-filling data structures, or initializing state for UI components. Manually listing each element is not only tedious but can also lead to longer code and increased risk of errors.</p>
<p>Swift provides a highly efficient and concise method for handling such cases: the <code>Array(repeating:count:)</code> initializer. This tool allows developers to create arrays with multiple copies of the same element, ensuring code is clean and maintainable.</p>
<pre><code class="lang-swift"><span class="hljs-class"><span class="hljs-keyword">enum</span> <span class="hljs-title">HorizontalIndent</span> </span>{
  <span class="hljs-keyword">case</span> <span class="hljs-keyword">left</span>
  <span class="hljs-keyword">case</span> <span class="hljs-keyword">right</span>

  <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">toggle</span><span class="hljs-params">()</span></span> -&gt; <span class="hljs-type">HorizontalIndent</span> {
    <span class="hljs-keyword">self</span> == .<span class="hljs-keyword">left</span> ? .<span class="hljs-keyword">right</span> : .<span class="hljs-keyword">left</span>
  }
}
<span class="hljs-keyword">let</span> startHorizontalIndent: <span class="hljs-type">HorizontalIndent</span> = .<span class="hljs-keyword">left</span>
<span class="hljs-keyword">let</span> horizontalIndents: [<span class="hljs-type">HorizontalIndent</span>] = [
      startHorizontalIndent,
      startHorizontalIndent,
      startHorizontalIndent,
      startHorizontalIndent,
      startHorizontalIndent.toggle(),
      startHorizontalIndent.toggle(),
      startHorizontalIndent.toggle(),
      startHorizontalIndent.toggle()
    ]

<span class="hljs-comment">//Here's how you could refactor your code:</span>

<span class="hljs-comment">// Create the array using an initializer and map to generate toggled values</span>
<span class="hljs-keyword">let</span> horizontalIndents: [<span class="hljs-type">HorizontalIndent</span>] = <span class="hljs-type">Array</span>(repeating: startHorizontalIndent, <span class="hljs-built_in">count</span>: <span class="hljs-number">4</span>) +
                                             <span class="hljs-type">Array</span>(repeating: startHorizontalIndent.toggle(), <span class="hljs-built_in">count</span>: <span class="hljs-number">4</span>)
</code></pre>
]]></content:encoded></item><item><title><![CDATA[GeometryReader in SwiftUI]]></title><description><![CDATA[GeometryReader in SwiftUI is a container view that provides you with the size and position of its content relative to its parent view. This is particularly useful when you want to create responsive designs that adapt to various screen sizes and orien...]]></description><link>https://truongnn.me/geometryreader-in-swiftui</link><guid isPermaLink="true">https://truongnn.me/geometryreader-in-swiftui</guid><category><![CDATA[SwiftUI]]></category><category><![CDATA[GeometryReader]]></category><dc:creator><![CDATA[Truong Nguyen]]></dc:creator><pubDate>Thu, 04 Apr 2024 02:49:13 GMT</pubDate><content:encoded><![CDATA[<p><code>GeometryReader</code> in SwiftUI is a container view that provides you with the size and position of its content relative to its parent view. This is particularly useful when you want to create responsive designs that adapt to various screen sizes and orientations.</p>
<p>Here's a basic example to demonstrate how to use <code>GeometryReader</code>. In this example, we will create a simple view where a text element dynamically sizes itself to be half the width of its parent view, thanks to the information provided by <code>GeometryReader</code>.</p>
<pre><code class="lang-plaintext">import SwiftUI

struct ContentView: View {
    var body: some View {
        // GeometryReader is used to read the geometry of the parent view
        GeometryReader { geometry in
            // Inside the GeometryReader, you can use the geometry proxy to access size, safeAreaInsets, and more.
            VStack {
                Text("Hello, World!")
                    // Set the width of the text to be half of the parent view's width.
                    .frame(width: geometry.size.width / 2)
                    // Center the text horizontally in the parent view.
                    .background(Color.green)
                Spacer()
            }
        }
        .background(Color.blue)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Enum type in Dart]]></title><description><![CDATA[Introduction
Enums used to represent a fixed number of constant values. They are a helpful way to model a set of related constants in a type-safe way. Using enums can make your code more readable and maintainable by providing meaningful names for the...]]></description><link>https://truongnn.me/enum-type-in-dart</link><guid isPermaLink="true">https://truongnn.me/enum-type-in-dart</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Dart]]></category><category><![CDATA[enum]]></category><dc:creator><![CDATA[Truong Nguyen]]></dc:creator><pubDate>Wed, 21 Feb 2024 09:11:01 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-introduction">Introduction</h1>
<p>Enums used to represent a fixed number of constant values. They are a helpful way to model a set of related constants in a type-safe way. Using enums can make your code more readable and maintainable by providing meaningful names for these values.</p>
<h1 id="heading-basic-usage-of-enum">Basic usage of Enum</h1>
<pre><code class="lang-dart"><span class="hljs-keyword">enum</span> Status {
  none,
  running,
  stopped,
  paused
}
</code></pre>
<h2 id="heading-accessing-enum-values">Accessing Enum Values</h2>
<pre><code class="lang-dart"><span class="hljs-keyword">var</span> currentStatus = Status.running;
</code></pre>
<h2 id="heading-using-enums-in-switch-statements">Using Enums in Switch Statements</h2>
<pre><code class="lang-dart"><span class="hljs-keyword">switch</span> (currentStatus) {
  <span class="hljs-keyword">case</span> Status.none:
    <span class="hljs-built_in">print</span>(<span class="hljs-string">'No operation is currently running.'</span>);
    <span class="hljs-keyword">break</span>;
  <span class="hljs-keyword">case</span> Status.running:
    <span class="hljs-built_in">print</span>(<span class="hljs-string">'Operation is running.'</span>);
    <span class="hljs-keyword">break</span>;
  <span class="hljs-keyword">case</span> Status.stopped:
    <span class="hljs-built_in">print</span>(<span class="hljs-string">'Operation has stopped.'</span>);
    <span class="hljs-keyword">break</span>;
  <span class="hljs-keyword">case</span> Status.paused:
    <span class="hljs-built_in">print</span>(<span class="hljs-string">'Operation is paused.'</span>);
    <span class="hljs-keyword">break</span>;
}
</code></pre>
<p><strong>Enum Values and Iteration</strong></p>
<pre><code class="lang-dart"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> status <span class="hljs-keyword">in</span> Status.values) {
  <span class="hljs-built_in">print</span>(<span class="hljs-string">'Status: <span class="hljs-subst">$status</span>, Index: <span class="hljs-subst">${status.index}</span>'</span>);
}
</code></pre>
<h1 id="heading-enum-enhancements">Enum <strong>Enhancements</strong></h1>
<p>The ability to add methods, getters, constructors, and fields directly within the enum declaration.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">enum</span> UserRole {
  admin,
  editor,
  viewer;

  <span class="hljs-comment">// Add a field to an enum</span>
  <span class="hljs-keyword">final</span> <span class="hljs-built_in">int</span> permissionLevel;

  <span class="hljs-comment">// Enum constructor</span>
  <span class="hljs-keyword">const</span> UserRole() : permissionLevel = _setPermissionLevel();

  <span class="hljs-comment">// Static method to determine permission level</span>
  <span class="hljs-keyword">static</span> <span class="hljs-built_in">int</span> _setPermissionLevel() {
    <span class="hljs-keyword">switch</span> (<span class="hljs-keyword">this</span>) {
      <span class="hljs-keyword">case</span> UserRole.admin:
        <span class="hljs-keyword">return</span> <span class="hljs-number">3</span>;
      <span class="hljs-keyword">case</span> UserRole.editor:
        <span class="hljs-keyword">return</span> <span class="hljs-number">2</span>;
      <span class="hljs-keyword">case</span> UserRole.viewer:
        <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
    }
  }

  <span class="hljs-comment">// Example of a method</span>
  <span class="hljs-built_in">bool</span> canEditContent() {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span> == UserRole.admin || <span class="hljs-keyword">this</span> == UserRole.editor;
  }

  <span class="hljs-comment">// Example of a getter</span>
  <span class="hljs-built_in">String</span> <span class="hljs-keyword">get</span> description {
    <span class="hljs-keyword">switch</span> (<span class="hljs-keyword">this</span>) {
      <span class="hljs-keyword">case</span> UserRole.admin:
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Can access and modify all content and settings."</span>;
      <span class="hljs-keyword">case</span> UserRole.editor:
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Can access and modify content."</span>;
      <span class="hljs-keyword">case</span> UserRole.viewer:
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Can view content."</span>;
    }
  }

  <span class="hljs-comment">// Factory constructor for creating an enum from a string</span>
  <span class="hljs-keyword">static</span> UserRole? fromString(<span class="hljs-built_in">String</span> roleAsString) {
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> role <span class="hljs-keyword">in</span> UserRole.values) {
      <span class="hljs-keyword">if</span> (role.toString().split(<span class="hljs-string">'.'</span>).last == roleAsString) {
        <span class="hljs-keyword">return</span> role;
      }
    }
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>; <span class="hljs-comment">// Return null or throw an exception if the string doesn't match</span>
  }
}
</code></pre>
<p>they do not support factory constructors in the same way classes do. Factory constructors are typically used in classes to control the instantiation process, which can involve returning instances of a class from a cache, creating instances of subtypes, or performing other custom instantiation logic.</p>
<p>The concept of a factory constructor doesn't directly apply to enums because you're not creating new instances in the way you might with a class.</p>
<pre><code class="lang-dart"><span class="hljs-keyword">enum</span> TaskStatus {
  pending(progressValue: <span class="hljs-number">0</span>),
  inProgress(progressValue: <span class="hljs-number">50</span>),
  done(progressValue: <span class="hljs-number">100</span>);

  <span class="hljs-keyword">final</span> <span class="hljs-built_in">int</span> progressValue;
  <span class="hljs-keyword">const</span> TaskStatus({<span class="hljs-keyword">required</span> <span class="hljs-keyword">this</span>.progressValue});

  <span class="hljs-keyword">static</span> TaskStatus fromProgress(<span class="hljs-built_in">int</span> progress) {
    <span class="hljs-keyword">if</span> (progress &lt;= <span class="hljs-number">0</span>) {
      <span class="hljs-keyword">return</span> TaskStatus.pending;
    } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (progress &lt; <span class="hljs-number">100</span>) {
      <span class="hljs-keyword">return</span> TaskStatus.inProgress;
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">return</span> TaskStatus.done;
    }
  }
}
</code></pre>
<pre><code class="lang-dart"><span class="hljs-keyword">void</span> main() {
  <span class="hljs-built_in">int</span> progress = <span class="hljs-number">75</span>; <span class="hljs-comment">// Example progress value</span>
  TaskStatus status = TaskStatus.fromProgress(progress);

  <span class="hljs-built_in">print</span>(<span class="hljs-string">'With progress at <span class="hljs-subst">$progress</span>%, the task is <span class="hljs-subst">${status.toString().split(<span class="hljs-string">'.'</span>).last}</span>.'</span>);
  <span class="hljs-comment">// Output: With progress at 75%, the task is inProgress.</span>
}
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Library Splitting in Dart]]></title><description><![CDATA[The part/part of keywords
Introduction
part:This keyword is used within a Dart file to indicate that the file is part of another file. The purpose is to include this file's contents into a single library, alongside the contents of the other file(s) d...]]></description><link>https://truongnn.me/library-splitting-in-dart</link><guid isPermaLink="true">https://truongnn.me/library-splitting-in-dart</guid><category><![CDATA[Flutter]]></category><category><![CDATA[#dart-for-beginners]]></category><dc:creator><![CDATA[Truong Nguyen]]></dc:creator><pubDate>Fri, 16 Feb 2024 09:31:38 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-the-partpart-of-keywords">The <code>part/part of</code> keywords</h1>
<h2 id="heading-introduction">Introduction</h2>
<p><code>part</code>:This keyword is used within a Dart file to indicate that the file is part of another file. The purpose is to include this file's contents into a single library, alongside the contents of the other file(s) designated as part of the same library.</p>
<p><code>part of:</code> It is used in the Dart files that are included as parts of another file. It indicates that the file is not standalone and should be considered as part of the library defined in another file. The file that uses <code>part of</code> must be included by the main library file using the <code>part</code> directive.</p>
<h2 id="heading-use-case-example">Use case example</h2>
<p>Let's use the example of building a car using <code>part</code>/<code>part of</code> directives. You're designing and building all parts of the car in-house (engine, tires, etc.), and you want to organize the design files for better manageability.</p>
<p><strong>CarLib.dart</strong></p>
<pre><code class="lang-dart"><span class="hljs-comment">// This is the main library file that declares all parts of the car.</span>
<span class="hljs-keyword">part</span> <span class="hljs-string">'EnginePart.dart'</span>;
<span class="hljs-keyword">part</span> <span class="hljs-string">'TiresPart.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{
  <span class="hljs-keyword">void</span> startCar() {
    Engine().start();
    Tires().roll();
  }
}
</code></pre>
<p><strong>EnginePart.dart:</strong></p>
<pre><code class="lang-dart"><span class="hljs-keyword">part</span> of <span class="hljs-string">'CarLib.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Engine</span> </span>{
  <span class="hljs-keyword">void</span> start() =&gt; <span class="hljs-built_in">print</span>(<span class="hljs-string">"Engine started"</span>);
}
</code></pre>
<p><strong>TiresPart.dart:</strong></p>
<pre><code class="lang-dart"><span class="hljs-keyword">part</span> of <span class="hljs-string">'CarLib.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Tires</span> </span>{
  <span class="hljs-keyword">void</span> roll() =&gt; <span class="hljs-built_in">print</span>(<span class="hljs-string">"Tires rolling"</span>);
}
</code></pre>
<p><code>EnginePart.dart</code> and <code>TiresPart.dart</code> are parts of the whole <code>CarLib.dart</code>. They can share private members among themselves because they're considered a single library (<code>CarLibrary.dart</code>). If <code>Engine</code> had a private method <code>_privateStart</code>, it could be called from <code>TiresPart.dart</code> or any other part of the same library.</p>
<h1 id="heading-the-import-keyword">The <code>import</code> keyword</h1>
<h2 id="heading-introduction-1">Introduction</h2>
<p>Used to include code from one file into another. This is like getting a tool from another toolbox to use in your current project. When you import a file, you're bringing in its public interfaces (such as classes, functions, and variables marked as <code>public</code>) so you can use them in your file. Ideal for reusing code and libraries without sharing the internal workings.</p>
<h2 id="heading-use-case-example-1">Use case example</h2>
<p>When building a car, you might need parts from different manufacturers: the engine from one company, the tires from another, and so on. Each of these parts has its own specifications and functionalities, and you integrate them into your car.</p>
<p><strong>Engine.dart</strong></p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Engine</span> </span>{
  <span class="hljs-keyword">void</span> start() =&gt; <span class="hljs-built_in">print</span>(<span class="hljs-string">"Engine started"</span>);
}
</code></pre>
<p><strong>Tires.dart</strong></p>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Tires</span> </span>{
  <span class="hljs-keyword">void</span> roll() =&gt; <span class="hljs-built_in">print</span>(<span class="hljs-string">"Tires rolling"</span>);
}
</code></pre>
<p><strong>CarLib.dart</strong></p>
<pre><code class="lang-dart"><span class="hljs-keyword">import</span> <span class="hljs-string">'Engine.dart'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'Tires.dart'</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{
  Engine engine = Engine();
  Tires tires = Tires();

  <span class="hljs-keyword">void</span> startCar() {
    engine.start();
    tires.roll();
  }
}
</code></pre>
<p><code>import</code> allows your <code>Car.dart</code> to use functionalities (like starting the engine or the tires rolling) from other files (<code>Engine.dart</code> and <code>Tires.dart</code>). However, if there are private methods or properties in <code>Engine</code> or <code>Tires</code> , you can't access them directly in <code>Car.dart</code> because they are encapsulated within their respective files</p>
<h1 id="heading-summary">Summary</h1>
<ul>
<li><p><code>import</code> is like sourcing car parts from different companies. Each part (file) is independent, and you can only use what is publicly available.</p>
</li>
<li><p><code>part</code><strong>/</strong><code>part of</code> is like designing and building every part of the car in-house, where all designs (files) are part of a single project, and every detail (including private ones) is accessible within the project.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Type casting in Dart]]></title><description><![CDATA[The "is" operator
Purpose
The is keyword in Dart is used for type checking. It evaluates to true if the object has the specified type, and false otherwise. This can be particularly useful when you need to ensure an object is of a certain type before ...]]></description><link>https://truongnn.me/type-casting-in-dart</link><guid isPermaLink="true">https://truongnn.me/type-casting-in-dart</guid><category><![CDATA[Flutter]]></category><category><![CDATA[type casting]]></category><dc:creator><![CDATA[Truong Nguyen]]></dc:creator><pubDate>Fri, 16 Feb 2024 05:32:14 GMT</pubDate><content:encoded><![CDATA[<h1 id="heading-the-is-operator">The "is" operator</h1>
<h2 id="heading-purpose">Purpose</h2>
<p>The <code>is</code> keyword in Dart is used for type checking. It evaluates to <code>true</code> if the object has the specified type, and <code>false</code> otherwise. This can be particularly useful when you need to ensure an object is of a certain type before performing operations or accessing properties specific to that type.</p>
<h2 id="heading-example">Example</h2>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span> </span>{
  <span class="hljs-keyword">void</span> breathe() {
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"Breathing"</span>);
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Fish</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span> </span>{
  <span class="hljs-keyword">void</span> swim() {
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"Swimming"</span>);
  }
}

<span class="hljs-keyword">void</span> main() {
  Animal a = Fish();

  <span class="hljs-keyword">if</span> (a <span class="hljs-keyword">is</span> Fish) {
    <span class="hljs-comment">// This block will execute because 'a' is indeed an instance of Fish</span>
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"It's a fish!"</span>);
    a.swim(); <span class="hljs-comment">// This is safe to call because we've checked that 'a' is a Fish</span>
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"It's not a fish"</span>);
  }
}
</code></pre>
<p>The <code>is</code> keyword is particularly useful in scenarios involving polymorphism or when dealing with collections of objects with a common superclass. It allows your code to dynamically identify the specific subtype of an object at runtime and safely perform type-specific operations.</p>
<p>Here's another example with a list of mixed types:</p>
<pre><code class="lang-dart"><span class="hljs-keyword">void</span> main() {
  <span class="hljs-built_in">List</span>&lt;Animal&gt; animals = [Fish(), Animal()];

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> animal <span class="hljs-keyword">in</span> animals) {
    <span class="hljs-keyword">if</span> (animal <span class="hljs-keyword">is</span> Fish) {
      (animal <span class="hljs-keyword">as</span> Fish).swim(); <span class="hljs-comment">// Casting is necessary to call swim</span>
    } <span class="hljs-keyword">else</span> {
      animal.breathe();
    }
  }
}
</code></pre>
<h1 id="heading-the-as-operator">The "as" operator</h1>
<h2 id="heading-purpose-1">Purpose</h2>
<p>The <code>as</code> keyword in Dart is used for typecast operations, allowing you to specify that an object belongs to a particular type. This can be useful in situations where you want to treat an instance of a superclass as if it were an instance of a subclass, or more generally, when you're sure that an object of a certain base type is actually a specific subtype and you want to access its properties or methods that aren't available on the base type.</p>
<h2 id="heading-example-1">Example</h2>
<pre><code class="lang-dart"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span> </span>{
  <span class="hljs-keyword">void</span> breathe() {
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"Breathing"</span>);
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Fish</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span> </span>{
  <span class="hljs-keyword">void</span> swim() {
    <span class="hljs-built_in">print</span>(<span class="hljs-string">"Swimming"</span>);
  }
}

<span class="hljs-keyword">void</span> main() {
  Animal a = Fish();

  <span class="hljs-comment">// Without casting, you can't call swim on an Animal</span>
  <span class="hljs-comment">// a.swim(); // This would be an error</span>

  <span class="hljs-comment">// Using 'as' to cast 'a' to Fish so we can call swim()</span>
  (a <span class="hljs-keyword">as</span> Fish).swim(); <span class="hljs-comment">// This works</span>

  <span class="hljs-comment">// This is also a way to assert the type at runtime.</span>
  <span class="hljs-comment">// If 'a' was not a Fish, this would throw a TypeError.</span>
}
</code></pre>
<p>It's important to use <code>as</code> cautiously, as it introduces the possibility of a runtime error if the object is not of the type you're casting to. Dart will throw a <code>TypeError</code> if the cast is invalid at runtime, which helps catch mistakes but also means you should be confident in your type assumptions when using <code>as</code></p>
<h1 id="heading-important-considerations"><strong>Important Considerations</strong></h1>
<ul>
<li><p><strong>Type Safety</strong>: While the <code>as</code> operator can override compile-time type checks, it can lead to runtime errors if the cast is incorrect. Use it judiciously and only when you are certain of the object's type.</p>
</li>
<li><p><strong>Performance</strong>: Frequent use of <code>as</code> and <code>is</code> might impact performance. It's best to design your code in a way that minimizes the need for type checks and casts.</p>
</li>
</ul>
]]></content:encoded></item></channel></rss>