<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Finite Field</title>
    <description>The latest articles on DEV Community by Finite Field (@finitefield).</description>
    <link>https://dev.to/finitefield</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2572565%2F7b2decb8-6184-43b7-b860-b54dd8b11780.png</url>
      <title>DEV Community: Finite Field</title>
      <link>https://dev.to/finitefield</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/finitefield"/>
    <language>en</language>
    <item>
      <title>Outlineを使ってLinuxサーバー上にVPNサーバーを構築する方法</title>
      <dc:creator>Finite Field</dc:creator>
      <pubDate>Tue, 17 Dec 2024 06:02:33 +0000</pubDate>
      <link>https://dev.to/finitefield/outlinewoshi-tutelinuxsabashang-nivpnsabawogou-zhu-surufang-fa-24a8</link>
      <guid>https://dev.to/finitefield/outlinewoshi-tutelinuxsabashang-nivpnsabawogou-zhu-surufang-fa-24a8</guid>
      <description>&lt;p&gt;近年、プライバシー保護やセキュリティ強化、コンテンツフィルタリングの回避などの理由から、VPN(Virtual Private Network)を利用するケースが増えています。自前でVPNサーバーを立てることで、信頼性やプライバシー、コスト面でのメリットを得ることができます。&lt;/p&gt;

&lt;p&gt;ここでは、Googleが支援するJigsaw社によって開発されたオープンソースツール「&lt;a href="https://getoutline.org/" rel="noopener noreferrer"&gt;Outline&lt;/a&gt;」を使用して、一般的なLinuxサーバー上にVPNサーバーをセットアップする方法を紹介します。Outlineは、比較的簡潔な手順で安全なプロキシ(VPN)サーバーを構築できることで知られています。&lt;/p&gt;

&lt;h2&gt;
  
  
  なぜOutlineを使うのか？
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;シンプルなセットアップ&lt;/strong&gt;：Outlineはコマンド一つでインストール・セットアップが可能な自動化ツールを提供しており、初心者でも扱いやすいです。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;マルチプラットフォーム対応&lt;/strong&gt;：クライアントはWindows、macOS、iOS、Android、Linuxなど幅広くサポートされており、どこからでも接続が可能です。&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;セキュアな通信&lt;/strong&gt;：Shadowsocksプロキシをベースにした暗号化通信を行うため、高度なセキュリティが期待できます。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  準備するもの
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Linuxサーバー&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;一般的なLinuxディストリビューション (Ubuntu, Debian, CentOSなど)でOK。
&lt;/li&gt;
&lt;li&gt;パブリックIPアドレスを持つVPSやクラウドサーバーを用いるとよいでしょう。
&lt;/li&gt;
&lt;li&gt;メモリ・CPU・ストレージは軽量構成で十分(1GB RAM程度、1 vCPU、10GB程度のストレージなど)。
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;サーバーへのアクセス権限&lt;/strong&gt;：  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSHでルートもしくはsudo権限を持つユーザーアクセスが必要。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;クライアント側の準備&lt;/strong&gt;：  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;後ほどOutlineクライアントアプリをインストールするため、接続したいデバイス(PC、スマホ、タブレットなど)が用意できる環境。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  インストール手順
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. サーバー環境の初期設定
&lt;/h3&gt;

&lt;p&gt;サーバーにSSHで接続します。以下はUbuntu系の場合の例です。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh username@your_server_ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;接続したら、サーバーパッケージの最新化を行います。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Dockerのインストール
&lt;/h3&gt;

&lt;p&gt;Outlineは内部的にDockerコンテナを使用します。そのため、Dockerが必要です。Ubuntu/Debianの場合:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; apt-transport-https ca-certificates curl software-properties-common
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://download.docker.com/linux/&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; /etc/os-release&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/gpg | &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-key add -
&lt;span class="nb"&gt;sudo &lt;/span&gt;add-apt-repository &lt;span class="s2"&gt;"deb [arch=amd64] https://download.docker.com/linux/&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; /etc/os-release&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;lsb_release &lt;span class="nt"&gt;-cs&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable"&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; docker-ce
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;インストール後、Dockerが正常に動作しているか確認します。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;docker
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start docker
&lt;span class="nb"&gt;sudo &lt;/span&gt;docker run hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Hello from Docker!&lt;/code&gt; と出れば成功です。&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Outlineサーバーのインストールツールをダウンロード
&lt;/h3&gt;

&lt;p&gt;Outline公式サイトの&lt;a href="https://getoutline.org/get-started" rel="noopener noreferrer"&gt;インストールガイド&lt;/a&gt;に従い、Linux版のOutline Manager CLI(サーバーインストーラー)を利用します。&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sSL&lt;/span&gt; https://raw.githubusercontent.com/Jigsaw-Code/outline-server/master/src/server_manager/install_scripts/install_server.sh | &lt;span class="nb"&gt;sudo &lt;/span&gt;bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;上記コマンドは、Outlineサーバーをインストールするためのスクリプトをダウンロードし、実行します。途中でDockerイメージがダウンロードされ、サーバーが設定されます。&lt;/p&gt;

&lt;h3&gt;
  
  
  4. サーバー管理情報の確認
&lt;/h3&gt;

&lt;p&gt;インストール完了後、ターミナルに「&lt;strong&gt;管理用URL (Management URL)&lt;/strong&gt;」や「&lt;strong&gt;アクセスキー (Access Key)&lt;/strong&gt;」が表示されます。これらは後でクライアントツール(Outline Manager)でサーバーを管理する際に必要となりますので、必ずメモしておきましょう。&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Outline Managerを使ってサーバーを管理
&lt;/h3&gt;

&lt;p&gt;ローカルのPC(Windows/Mac/Linux)に&lt;a href="https://getoutline.org/" rel="noopener noreferrer"&gt;Outline Manager&lt;/a&gt;アプリをインストールします。起動後、「Add a Server」や「サーバーを追加」ボタンを押し、先ほど取得した管理用URLを入力します。&lt;/p&gt;

&lt;p&gt;これで、Outline ManagerからVPNサーバーにアクセスし、ユーザー(アクセスキー)を追加したり、接続情報を取得したりすることが可能になります。&lt;/p&gt;

&lt;h3&gt;
  
  
  6. クライアントアプリのセットアップ
&lt;/h3&gt;

&lt;p&gt;接続したいクライアントデバイス(スマホやPC)に&lt;a href="https://getoutline.org/" rel="noopener noreferrer"&gt;Outline Client&lt;/a&gt;をインストールします。Outline Managerから取得したアクセスキー(接続キー)をクライアントアプリに読み込ませると、VPN接続が可能になります。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;例&lt;/strong&gt;：

&lt;ol&gt;
&lt;li&gt;Outline Clientをインストール
&lt;/li&gt;
&lt;li&gt;Managerから取得した「Access Key」をクリップボードコピー
&lt;/li&gt;
&lt;li&gt;Clientアプリの「+」ボタンや「Add Server」でキーをペースト
&lt;/li&gt;
&lt;li&gt;サーバーが追加されるので「Connect」ボタンで接続開始&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;接続後、Webブラウザで自分のIPアドレスをチェックすると、サーバーのIPアドレスで通信が行われていることが確認できます。&lt;/p&gt;

&lt;p&gt;Outlineを使用すれば、わずか数ステップで安全なVPNサーバー(シャドーソックスプロキシ)を構築できます。自前サーバーによるVPN環境は、商用VPNに比べコントロール性やプライバシー面でのメリットが大きく、簡単な操作で世界中どこからでもセキュアなインターネット接続が可能になります。&lt;/p&gt;

&lt;p&gt;レンタルサーバに関して、&lt;a href="https://serverfield.org" rel="noopener noreferrer"&gt;サーバーフィールド&lt;/a&gt;には様々な記事があります。どうぞご覧ください。また、Webサイト作成はどうぞ&lt;a href="https://finitefield.org" rel="noopener noreferrer"&gt;弊社（ファイナイトフィールド）&lt;/a&gt;にお任せください。&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Dart's Sealed Classes: A Powerful Tool for Type Safety and Exhaustiveness</title>
      <dc:creator>Finite Field</dc:creator>
      <pubDate>Sun, 15 Dec 2024 13:12:51 +0000</pubDate>
      <link>https://dev.to/finitefield/darts-sealed-classes-a-powerful-tool-for-type-safety-and-exhaustiveness-nc9</link>
      <guid>https://dev.to/finitefield/darts-sealed-classes-a-powerful-tool-for-type-safety-and-exhaustiveness-nc9</guid>
      <description>&lt;p&gt;Dart, like many modern languages, is continually evolving to provide developers with better tools for writing robust and maintainable code. One feature that significantly enhances type safety and code clarity is the &lt;code&gt;sealed&lt;/code&gt; class modifier. Introduced in Dart 3.0, &lt;code&gt;sealed&lt;/code&gt; classes offer a way to restrict the inheritance hierarchy of a class, enabling powerful patterns and catching potential errors at compile time.&lt;/p&gt;

&lt;p&gt;In this post, we'll delve into what sealed classes are, how they work, and why you should consider using them in your Dart projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are Sealed Classes?
&lt;/h3&gt;

&lt;p&gt;At their core, &lt;code&gt;sealed&lt;/code&gt; classes are a mechanism for defining a class that can only be inherited by a specific, predefined set of subclasses. In essence, a &lt;code&gt;sealed&lt;/code&gt; class creates a closed hierarchy. This is a powerful contrast to regular classes, which can be extended by any other class in your application.&lt;/p&gt;

&lt;p&gt;Think of it like this: a regular class is a door that anyone can enter, while a &lt;code&gt;sealed&lt;/code&gt; class is a door with a very specific list of allowed visitors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key characteristics of sealed classes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Restricted Inheritance:&lt;/strong&gt; Only the classes declared within the same library as the &lt;code&gt;sealed&lt;/code&gt; class can extend or implement it.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Compile-Time Exhaustiveness:&lt;/strong&gt; When working with a &lt;code&gt;sealed&lt;/code&gt; class, the Dart compiler can enforce that your code handles all possible subclasses. This leads to more robust code and prevents potential runtime errors.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;No Implementation:&lt;/strong&gt; A sealed class does not have to have any implementation. It is simply a marker class.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Syntax of Sealed Classes
&lt;/h3&gt;

&lt;p&gt;Declaring a sealed class is straightforward. You simply add the &lt;code&gt;sealed&lt;/code&gt; keyword before the &lt;code&gt;class&lt;/code&gt; keyword:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;sealed&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's define some allowed subclasses within the &lt;em&gt;same&lt;/em&gt; library (usually in the same file):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;sealed&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Circle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Circle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Square&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;side&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;side&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Triangle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="kd"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Triangle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// This won't compile because it's in a different file&lt;/span&gt;
&lt;span class="c1"&gt;//class Rectangle extends Shape {}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, &lt;code&gt;Shape&lt;/code&gt; is our &lt;code&gt;sealed&lt;/code&gt; class, and &lt;code&gt;Circle&lt;/code&gt;, &lt;code&gt;Square&lt;/code&gt;, and &lt;code&gt;Triangle&lt;/code&gt; are the only classes that can inherit from it. If you try to create another class in a &lt;em&gt;different file&lt;/em&gt; that extends &lt;code&gt;Shape&lt;/code&gt;, you'll get a compile-time error.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Power of Exhaustiveness
&lt;/h3&gt;

&lt;p&gt;The real magic of sealed classes lies in the compile-time exhaustiveness check. Dart can use the information about the limited number of subclasses of a &lt;code&gt;sealed&lt;/code&gt; class to ensure that your &lt;code&gt;switch&lt;/code&gt; statements or &lt;code&gt;if/else&lt;/code&gt; chains cover all the possible cases.&lt;/p&gt;

&lt;p&gt;Here's how that looks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;sealed&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Circle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Circle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Square&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;side&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;side&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Triangle&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Shape&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="kd"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Triangle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;calculateArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Shape&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;Circle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;3.14&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;Square&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;side&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;side&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;Triangle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;base&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;calculateArea&lt;/code&gt; function, if you were to forget one of the cases (e.g., the &lt;code&gt;Triangle&lt;/code&gt; case), the Dart compiler would throw an error. This immediately points out that your code is incomplete and helps prevent potential runtime bugs. This is why &lt;code&gt;sealed&lt;/code&gt; classes are particularly useful in combination with pattern matching.&lt;/p&gt;

&lt;p&gt;With regular classes, if you add a new subclass, your old code may break silently at runtime. The compiler will not give a warning because it doesn't know that the subclasses are closed. But, in the case of &lt;code&gt;sealed&lt;/code&gt; classes, the compiler gives a compile-time error forcing you to address it immediately, leading to more robust and maintainable code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Cases for Sealed Classes
&lt;/h3&gt;

&lt;p&gt;Sealed classes are a valuable tool in several scenarios:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;State Management:&lt;/strong&gt; When managing application state, you often have a distinct set of states that an object can be in. Using a sealed class to represent the possible states ensures your code handles them all correctly. This is particularly helpful when you are dealing with asynchronous operations. For example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;sealed&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DataState&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Loading&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;DataState&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Loaded&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;DataState&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;dynamic&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Loaded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;DataState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;errorMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;errorMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Algebraic Data Types (ADTs):&lt;/strong&gt; Sealed classes excel at modeling ADTs, where data can take on a finite set of forms. This enables you to express your domain logic very clearly and have the compiler enforce that your code correctly handles all the possible cases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Representing Events:&lt;/strong&gt; In event-driven architectures, sealed classes can represent different event types. This allows you to build event handlers that are guaranteed to cover all possible events.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Exhaustive switch cases:&lt;/strong&gt; The compiler enforces that you have handled all the possible type with in switch statement.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Benefits of Using Sealed Classes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Enhanced Type Safety:&lt;/strong&gt; Compile-time checks help you catch missing cases, reducing runtime errors.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Improved Code Maintainability:&lt;/strong&gt; The compiler forces you to revisit and update the relevant code when new subclasses are added, preventing your application from breaking silently.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Clearer Domain Modeling:&lt;/strong&gt; Sealed classes help you precisely express the structure of your data, making it more understandable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;sealed&lt;/code&gt; class modifier is a significant addition to Dart, bringing compile-time exhaustiveness and improved type safety. They're a valuable tool to add to your development arsenal, particularly when dealing with state, ADTs, events, or any situation where you have a well-defined set of types that you need to handle exhaustively.&lt;/p&gt;

&lt;p&gt;By adopting sealed classes, you can write more robust, maintainable, and less error-prone Dart code. So, next time you're working on a Flutter or Dart project, consider if a sealed class could help streamline your logic. At &lt;a href="https://finitefield.org" rel="noopener noreferrer"&gt;Finite Field&lt;/a&gt;, we understand the power of cutting-edge features like sealed classes. As a dedicated app development company, we leverage these kinds of tools, along with deep expertise in Flutter and Dart, to craft innovative and high-quality mobile applications for our clients. If you're looking for a partner to bring your app idea to life with a focus on maintainable and scalable code, we'd love to hear from you.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Level Up Your Flutter App: Mastering the SearchBar Widget</title>
      <dc:creator>Finite Field</dc:creator>
      <pubDate>Sun, 15 Dec 2024 13:11:13 +0000</pubDate>
      <link>https://dev.to/finitefield/level-up-your-flutter-app-mastering-the-searchbar-widget-30mn</link>
      <guid>https://dev.to/finitefield/level-up-your-flutter-app-mastering-the-searchbar-widget-30mn</guid>
      <description>&lt;p&gt;In today's apps, users expect seamless search functionality. Whether it's finding a specific product, locating a contact, or sifting through a list of articles, a good search experience is crucial. Luckily, Flutter provides the &lt;code&gt;SearchBar&lt;/code&gt; widget to make implementing search functionality a breeze.&lt;/p&gt;

&lt;p&gt;This post will guide you through everything you need to know to effectively use the &lt;code&gt;SearchBar&lt;/code&gt; in your Flutter applications. We'll cover basic setup, handling user input, displaying results, and some common customization options.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's dive in!&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting Started: The Basic Setup
&lt;/h3&gt;

&lt;p&gt;Before we get to the search logic, we need to set up our &lt;code&gt;SearchBar&lt;/code&gt; widget within our Flutter UI. Here's the most basic implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SearchExample&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatefulWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;_SearchExampleState&lt;/span&gt; &lt;span class="n"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_SearchExampleState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_SearchExampleState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SearchExample&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;_searchText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;appBar:&lt;/span&gt; &lt;span class="n"&gt;AppBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Search Example'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;Padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;padding:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;16.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;SearchBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;hintText:&lt;/span&gt; &lt;span class="s"&gt;'Search here...'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nl"&gt;onChanged:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="n"&gt;_searchText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="c1"&gt;// You'll add search logic here later&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What's happening here?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;SearchBar&lt;/code&gt; Widget:&lt;/strong&gt; We've added the &lt;code&gt;SearchBar&lt;/code&gt; widget directly into our widget tree, which takes care of the visual layout of the search bar.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;hintText&lt;/code&gt;:&lt;/strong&gt; This provides a helpful placeholder text inside the search bar.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;onChanged&lt;/code&gt; Callback:&lt;/strong&gt; This function is triggered every time the user types or deletes something in the search bar. This is where our search logic will live!&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;_searchText&lt;/code&gt; Variable:&lt;/strong&gt; We use a &lt;code&gt;StatefulWidget&lt;/code&gt; to manage the search text as the user types.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;setState&lt;/code&gt;:&lt;/strong&gt; We update the &lt;code&gt;_searchText&lt;/code&gt; using &lt;code&gt;setState&lt;/code&gt;, which triggers a rebuild and shows the updated value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you run this code, you'll have a basic working search bar that updates the &lt;code&gt;_searchText&lt;/code&gt; variable!&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Search Logic
&lt;/h3&gt;

&lt;p&gt;Now, let's make the search bar actually &lt;em&gt;do&lt;/em&gt; something. We'll assume we have a simple list of items that we want to search through. Here's how we can update the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:flutter/material.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SearchExample&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatefulWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;_SearchExampleState&lt;/span&gt; &lt;span class="n"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_SearchExampleState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_SearchExampleState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SearchExample&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;_searchText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_allNames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'Apple'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Banana'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Cherry'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Date'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Elderberry'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Fig'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;//Example Data&lt;/span&gt;
  &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_filteredNames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;appBar:&lt;/span&gt; &lt;span class="n"&gt;AppBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Search Example'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;Padding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;padding:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;16.0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;SearchBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="nl"&gt;hintText:&lt;/span&gt; &lt;span class="s"&gt;'Search Names...'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="nl"&gt;onChanged:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;_searchText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isNotEmpty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                   &lt;span class="n"&gt;_filteredNames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_allNames&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                          &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
                            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;_filteredNames&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
                  &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="p"&gt;});&lt;/span&gt;
              &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;SizedBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;height:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;Expanded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;ListView&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                  &lt;span class="nl"&gt;itemCount:&lt;/span&gt; &lt;span class="n"&gt;_searchText&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;_allNames&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;_filteredNames&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="nl"&gt;itemBuilder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ListTile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_searchText&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isEmpty&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;_allNames&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;_filteredNames&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
                  &lt;span class="p"&gt;);&lt;/span&gt;
                  &lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Changes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;_allNames&lt;/code&gt;:&lt;/strong&gt; A sample list of strings we'll be searching through.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;_filteredNames&lt;/code&gt;:&lt;/strong&gt; This list will store the search results.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Search Logic:&lt;/strong&gt; Inside the &lt;code&gt;onChanged&lt;/code&gt; callback:

&lt;ul&gt;
&lt;li&gt;  We check if the search text is not empty. If it is not empty we use the &lt;code&gt;.where&lt;/code&gt; method to filter the &lt;code&gt;_allNames&lt;/code&gt; based on a substring match (case-insensitive).&lt;/li&gt;
&lt;li&gt;  If the search text is empty we set the &lt;code&gt;_filteredNames&lt;/code&gt; to empty list.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;&lt;code&gt;ListView.builder&lt;/code&gt;&lt;/strong&gt; Now we display either all names or the filtered name depending on the state of the search text.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Now, as you type in the search bar, the list of names will update in real-time to show only the matching results.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customizing the &lt;code&gt;SearchBar&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;SearchBar&lt;/code&gt; widget offers several ways to customize its appearance and behavior. Here are a few of the most common:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;controller&lt;/code&gt;:&lt;/strong&gt; You can use a &lt;code&gt;TextEditingController&lt;/code&gt; to control the input of the search bar. This is useful if you need to pre-populate the search bar or programmatically clear it.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;leading&lt;/code&gt; and &lt;code&gt;trailing&lt;/code&gt;:&lt;/strong&gt; Add widgets (such as Icons) before and after the input field.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;&lt;code&gt;backgroundColor&lt;/code&gt; and other styling properties:&lt;/strong&gt; Use these to change the look and feel of the search bar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a quick example of using a &lt;code&gt;leading&lt;/code&gt; icon and changing the background color:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;SearchBar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;hintText:&lt;/span&gt; &lt;span class="s"&gt;'Search...'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;backgroundColor:&lt;/span&gt; &lt;span class="n"&gt;MaterialStateProperty&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;grey&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
  &lt;span class="nl"&gt;leading:&lt;/span&gt; &lt;span class="n"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;search&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nl"&gt;onChanged:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Beyond the Basics
&lt;/h3&gt;

&lt;p&gt;This blog post provides a foundation for working with the &lt;code&gt;SearchBar&lt;/code&gt; widget. Here are some ideas for taking your search functionality further:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Debouncing:&lt;/strong&gt; Prevent your search logic from running on every single keystroke by using a debouncer. This can significantly improve performance.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;API Integration:&lt;/strong&gt; Fetch search results from an API instead of a local list.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Loading Indicators:&lt;/strong&gt; Provide feedback to the user while results are loading from an API.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Search Suggestions:&lt;/strong&gt; Offer suggestions as the user types to help them find what they are looking for quickly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;SearchBar&lt;/code&gt; widget is a powerful and flexible tool for building search functionality in Flutter. By following the techniques outlined in this blog post, you'll be well on your way to crafting excellent user experiences in your Flutter applications.&lt;/p&gt;

&lt;p&gt;At &lt;a href="https://finitefield.org" rel="noopener noreferrer"&gt;Finite Field&lt;/a&gt;, we understand the power of cutting-edge features like &lt;code&gt;SearchBar&lt;/code&gt;. As a dedicated app development company, we leverage these kinds of tools, along with deep expertise in Flutter and Dart, to craft innovative and high-quality mobile applications for our clients. If you're looking for a partner to bring your app idea to life with a focus on maintainable and scalable code, we'd love to hear from you.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
