LoginSignup
5
4

More than 3 years have passed since last update.

ハンズオンで学ぶFlutter(状態管理編)

Posted at

以前の振り返り

以前の記事でFlutterのUI構築をハンズオン形式で学んでいきました。
具体的には、Flutterとは何か、StatelessWidgt、StatefulWidgetの違い、その他のWidgetなどを学んでいきました。以下のURLから見てください。
Flutterハンズオン(UI構築編)

以前の記事で、とりあえず見た目の部分は完成したので、今回の記事で状態管理の方法を学び、実際にニュースのデータを取ってきて表示していきましょう。

git clone https://github.com/shokiogawa/hands_on.git

にコードのデータがあるので、こちらのコードをベースに進めてください。

Flutterでの状態管理

今の段階では、statelessWidgetを使っています。しかし、状態を管理するため、stateFulWidgetを使用しないといけないかというと、そうではありません。
もちろん、statefulwidgetを使用した方法もあるのですが、今回は、状態管理にProviderというライブラリを活用します。
このproviderを使うと、statelesswidgetなのかstatefulwidgetなのかを意識することなく状態を管理することが出来ます。

Providerとは??

Providerとはパッケージの名前で、Flutterの状態管理の一つの手法です。
手法の一つといったようにFlutterには多くの状態管理の方法があります。しかし、そのなかでもGoogleはprovider推奨しています。
詳しくはFlutterの状態管理から見てください。

また、このproviderの中でも、複数の状態管理手法があります。
・Provider
・change_notifier
・state_notifier
etc...
この中で、今回はstate_notifierを使い状態管理をしていきます。
また、state_notifierと同時にfreezedというパッケージも合わせて使用します。

freezedとは

freezedは、イミュータブルなデータモデルを作成するために使うパケージです。
また、stateにcopyWithというメソッドが自動で作成されます。

state_notifierは管理する状態をイミュータブルなものとして扱うため、freezedと相性が良いです。

言葉で説明されても難しいと思うので実際にコードを書きながら学んでいきましょう。

state_notifierとfreezedを使った状態管理

Flutterでこれらのパッケージを使い状態管理をする場合、いくつかのステップがあります。

  1. パッケージをインストール
  2. freezedでイミュータブルなデータを管理するクラスを作成する。
  3. 1.で作成したデータクラスをもとにfreezedのパッケージを使い自動でコードを生成する。(ここで、copyWithなどのメソッドが生成される。)
  4. 1.で作成したデータモデルをもとに、状態を変化させるロジックなどを管理するクラスを作成する。(クラスはstateNotifierを継承)

ここでわかる通り、二つのクラスを作成します。
1つは状態を保管するクラス(freezed)。
もう1つはその状態を変化させるためのクラス(state_notifier)です。

ステップ1: 必要なパッケージをインストールする

pubspec.yamlに以下のパッケージを記述しインストールします。

dependencies:
  flutter:
    sdk: flutter
  provider: ^4.1.0-dev
  state_notifier: ^0.4.0
  flutter_state_notifier: ^0.3.0
  freezed_annotation:

dev_dependencies:
  flutter_test:
    sdk: flutter
  build_runner:
  freezed:

開発日によってそれぞれのバージョンが異なる可能性があるので、一つ一つチェックしてください。
state_notifier
flutter_state_notifier
freezed
freezed_annotation
provider
build_runner

ステップ2: freezedでイミュータブルなデータを管理するクラスを作成する

lib/presentation/controller/news_controller.dart
part 'news_controller.freezed.dart';
@freezed
abstract class NewsState with _$NewsState {
  factory NewsState({
    List<Article> articles,
  }) = _NewsState;
}

ここでは、ニュースの情報を管理するクラスの名前を、NewsStateとします。
NewsStateクラスの中にあるarticles(型 List )にニュースのデータが入ります。

今の段階では、エラーが出ると思いますが、いまはほっておいて大丈夫です。

ステップ3: freezedのパッケージを使いコードを自動生成。

コードを自動生成していきます。
ターミナルで、flutter pub run build_runner buildと打つと、自動でコードが生成されます。
news_controller.dartがあるディレクトリにnews_controller.freezed.dartというファイルが自動で作られたと思います。

この段階でステップ2で出ていたエラーが消えたかと思います。

ステップ4: 状態を変化させるロジックなどを管理するクラスを作成する

今回は、apiからnewのデータを取ってきたいので、newsデータを取ってきて、ステップ1で作成したarticlesに代入するロジックをこのクラスで書きます。

lib/presentation/controller/news_controller.dart

class NewsController extends StateNotifier<NewsState> {

  //apiからデータを照ってくる処理が書いてあるクラスのインスタンス化
  NewsQueryService _newsQueryService = NewsQueryService();

  NewsController() : super(NewsState());

  //ニュース情報を、apiからとってきて、NewsStateの中のarticlesに格納するメソッド
  Future<void> getNews() async {
    List<Article> articles = [];
    articles = await _newsQueryService.getNews();

    //NewsStateで格納しているデータの変更処理(state変数にすべて格納されている)
    //データの変更するためには、copyWithメソッドを使用する。
    state = state.copyWith(articles: articles);
  }
}

上のコードで書かれている、getNewsメソッドでニュースデータをapiからとってきて、NewsStateクラスの中のarticlesに格納しています。

ちなみに、NewsQueryServiceクラスに関しては、

lib/infrastructure/news_query_service.dart

class NewsQueryService {
  final ApiService _apiService = ApiService.create();

  Future<List<Article>> getNews() async {
    Response response;
    List<Article> result = List<Article>();

    try {
      response = await _apiService.getHeadlines();
      if (response.isSuccessful) {
        final responseBody = response.body;
        result = News.fromJson(responseBody).articles;
      } else {
        final error = response.error;
        print('isSuccessful$error');
      }
    } catch (error) {}

    return result;
  }
}

となっており、NewsQueryServiceクラスのgetNewsメソッドはListのArticleを返しています。それを、NewsControllerのメソッドで、NwesState内のarticlesに格納しています。
他にも必要なコードがありますが、こちらで提供します。

これで、apiからのデータをNewsStateのクラスに格納することに成功しました。

次は、実際にそのデータを画面に表示していきます。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4