フリッターフリーズ- immutableのとの作業


不変のオブジェクトがあなたの人生をはるかに簡単にすることができます.フリーズはimmutableのとフラッターでの作業を簡素化するためにここにある.彼らが言うように:ユニオン/パターンマッチング/コピーのためのさらにもう一つのコードジェネレータ.彼らは機能の数を損なうことなく簡単な構文を約束します.我々が始める前に、正確に不変のオブジェクトであるものを簡単に見ましょう.

An object whose state cannot be changed after construction

https://en.wikipedia.org/wiki/Immutable_object


しかし、なぜimmutableの仕事をしたいですか?これはほぼすべてのプログラミング言語に質問されます.変更可能オブジェクトに比べていくつかの利点
  • 不変性は、コード
  • について理由をより簡単にします
    不変のオブジェクトはスレッドセーフです
  • コンストラクタ
  • の状態を有効にすることで、不正な状態を防止します

    プロジェクトのセットアップ


    コーディングを始める前に、プロジェクトにFreezed依存関係を追加する予定です.
    dependencies:
      flutter:
        sdk: flutter
      freezed_annotation: ^0.12.0
    
    dev_dependencies:
      build_runner:
      freezed: ^0.12.2
    
    依存関係をインストールすることを忘れないでください.
    flutter pub get
    

    変更不能オブジェクトの作成


    次の例を書き直します.それぞれの食べ物の名前と価格があります.リストを表示するにはListViewを使用します.したがって、我々は、新しいウィジェットに、私たちのケースでは、名前と価格を表示するリストタイルを食品オブジェクトをマップする必要があります.
    class FoodList extends StatelessWidget {
      final List foods = [Food("Banana", 10.0)];
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            Flexible(
              child: ListView.builder(
                  itemCount: foods.length,
                  itemBuilder: (BuildContext context, int index) {
                    var food = foods[index];
                    return ListTile(
                      title: Text(food.name),
                      subtitle: Text("€ ${food.price}"),
                    );
                  }),
            ),
          ],
        );
      }
    }
    
    class Food {
      final String name;
      final double price;
      Food(this.name, this.price);
    }
    
    もちろん、ここで食べ物のオブジェクトは面白い部分です.言い換えれば、我々は食品オブジェクトを変更不能にするつもりです.私たちは注釈を追加することによってこれを行うことができます@ freezed.さらに、クラスを抽象化し、コンストラクタとしてファクトリメソッドを追加する必要があります.最後に、凍結されたファイルで生成される部分文を追加しなければなりません.このオブジェクトを含むファイルは食べ物と呼ばれます.ダート、我々は次のステートメントを追加します.凍結した.ダーツ';
    import 'package:freezed_annotation/freezed_annotation.dart';
    import 'package:flutter/foundation.dart';
    
    part 'food.freezed.dart';
    
    @freezed
    abstract class Food with _$Food {
      factory Food({String name, double price}) = _Food;
    }
    
    あなたが沿ってコーディングしている場合は、エラーの多くが表示されます!心配しないでください、私たちがまだファイルを生成していないので、これは通常です.ファイルを生成するには、次のコマンドを実行します.
    flutter pub run build_runner build
    
    今、我々は元のリストを更新する予定です.ここでは、名前付きパラメータを持つオブジェクトを作成できます.しかし、我々はまた、名前と価格なしで新しい食品オブジェクトを作成することができます.
      final List foods = [Food(name: "Banana", price: 10.0), Food()];
    
    が発生することを防ぐために複数のオプションがあります.最初に@必須注釈を追加することです.次に、変数のデフォルト値を
    注釈.第三に、変数はオプションではないことを確認するために、ファクトリメソッドを変更することができます.
    // option 1
    @freezed
    abstract class Food with _$Food {
      factory Food({@required String name, @Default(10) double price}) = _Food;
    }
    // option 2
    @freezed
    abstract class Food with _$Food {
      factory Food(String name, double price) = _Food;
    }
    
    変更後に発電機を再起動することを忘れないでください!
    リストの現在の表示

    フラッタにおけるユニオンオブジェクト


    フリーズは、別のクールな機能、すなわちユニオンオブジェクトを提供します.ユニオンオブジェクトを使用すると、簡単にさまざまな種類の食品を作成することができます.たとえば、我々は1 kg当たり支払われる食品と食料ごとに支払われる食品を持っていると仮定します.つのオプションの両方を簡単に作成することができます.
    @freezed
    abstract class Food with _$Food {
      factory Food.perKg({@required String name, @Default(10) double price}) = FoodPerKg;
      factory Food.perPiece({@required String name, double price, @Default(1) int min}) = FoodPerPiece;
    }
    
    リストを更新するには、別の食品オブジェクトを作成する予定です.これで、リスト内の食品オブジェクトを別のウィジェットにマップできます.マップ機能は、異なるオプションを検出し、あなただけの機能を実装する必要があります.
    class FoodList extends StatelessWidget {
      final List foods = [
        Food.perKg(name: "Banana", price: 10.0),
        Food.perPiece(name: "Candy", price: 5.0, min: 2)
      ];
    
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            Flexible(
              child: ListView.builder(
                  itemCount: foods.length,
                  itemBuilder: (BuildContext context, int index) {
                    var food = foods[index];
                    return food.map(
                        perKg: (Food food) => ListTile(
                            title: Text(food.name),
                            subtitle: Text("€ ${food.price} per kg")),
                        perPiece: (FoodPerPiece food) => ListTile(
                            title: Text(food.name),
                            subtitle: Text(
                                "€ ${food.price} per piece, min ${food.min}")));
                  }),
            ),
          ],
        );
      }
    }
    
    ユニオンオブジェクトを処理するのに役立つ機能があります.

  • MayBegap、マップと同じですが、各ケースを実装する必要はありませんし、フォールバックオプションにorotherを追加します
  •                 return food.maybeMap(
                        perPiece: (FoodPerPiece food) => ListTile(
                            title: Text(food.name),
                            subtitle:
                                Text("€ ${food.price} per piece, min ${food.min}")),
                        // we do have access to both name and price, since both object contain name and price
                        orElse: () => ListTile(
                            title: Text(food.name),
                            subtitle: Text("€ ${food.price}")));
    

  • mapと同じです.
  •                 return food.when(
                        perKg: (String name, double price) => ListTile(
                            title: Text(name),
                            subtitle: Text("€ $price")),
                        perPiece: (String name, double price, int min) => ListTile(
                            title: Text(name),
                            subtitle: Text("€ $price per piece, min $min")));
                  }),
    
    

  • maybewhenと同じですが、それぞれのケースを実装する必要がなく、フォールバックオプションにorelseを追加する必要があります
  •                 return food.maybeWhen(
                        perPiece: (String name, double price, int min) => ListTile(
                            title: Text(name),
                            subtitle:
                                Text("€ $price per piece, min $min")),
                        // we do have access to both name and price, since both object contain name and price
                        orElse: () => ListTile(
                            title: Text(food.name),
                            subtitle: Text("€ ${food.price}")));
                  }),
    
    
    異なるタイプのリスト!

    フリーズしたオブジェクトをコピーする


    状態管理ソリューションのいくつかの間、状態が新しい値に設定されたときに状態が更新されます.このため、コピー機能は大きな助けです.我々が作成した食物オブジェクトが我々の状態であると仮定しましょう.我々が我々の状態を更新したいならば、我々はオリジナルの食物オブジェクトの価値で新しい食物オブジェクトをつくりました.
    // before
     void updatePrice(Food food, double newPrice) {
        state = Food(food.name, newPrice);
      }// after
     void updatePrice(Food food, double newPrice) {
        state = food.copyWith(price: newPrice);
      }
    
    現在、私たちはオブジェクトに2つの値しか持っていませんが、あなたのオブジェクトがより複雑になっているならば、Copyby関数はなります.しかし、新しい価格を更新することに興味があるだけで、コードはすでにより明確になります.CopyAwithなしでは、他の変数についても考えなければなりません.次のブログ記事では、このパッケージをwith the Riverpod State Management solution described earlier.

    結論


    これらは、フリーズで利用できるように作られた機能の一部です.それはあなたのコードを生成することによって、ビルドプロセスは少し複雑になりますが、それはあなたの人生を簡単に多くの方法で行います.いつものようにあなたのユースケースのトレードオフを考慮する必要があります.あなたのオブジェクトが多くを変えるならば、考慮されるパフォーマンストレードオフもあるかもしれません.
    Flutter Freezed – Working with Immutable’s年には、Barttjeが初めて登場した.