SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Flutterで始めるモバイルアプリ開発

Flutterでのデータ連携・処理について解説!~非同期処理と画面の連携機能を作ろう~

Flutterで始めるモバイルアプリ開発 第21回


データ処理と画面の分離

 先ほどの画面のコード内でも紹介しましたが、ILoginControllerというクラスが初期設定用のデータの取得とログイン処理をするためのクラスになります。画面表示と処理を分離する方法はさまざまな方法がありますが、ここではできるだけ他のライブラリなどに依存せず簡単にできるようにしています。

 ただし、ILoginControllerというクラスには処理の実装はなく、実装に応じたクラスを図2のように定義する想定です。

図2:処理の定義と実装の分離構造とクラスの関係
図2:処理の定義と実装の分離構造とクラスの関係

 このように分けた理由としては、今回紹介する画面動作を確認するための実装から、次回紹介するhttpを用いた実装へと切り替えた際にも画面側の変更を最小にするためです。

 また、ILoginControllerクラスの実装がリスト3です。

[リスト3]ログインで必要なデータ処理の定義クラス(lib/controller/ILoginController.dartの抜粋)
import 'package:chat_app/data/Response.dart';
// (1) abstractクラスとして定義
abstract class ILoginController{
    // (2) 初期設定の読込
    Future config();
    // (3) ログイン処理
    Future login(String loginId,String password);
    // (4) 終了処理
    void dispose(){
    }
}

 Flutterではインターフェースクラスはないので、(1)のようにabstractクラスとして定義しています。クラス名の名前に"I"をつけているのはインターフェース的な役割を意味するためですが、特にそれ以上の意味はありません。

 また、実際の(2)設定の取得や、(3)ログイン処理は実装クラスで行うことを前提としています。終了処理として(4)のdisposeメソッドを用意していますが、こちらは実装により後処理が必要なケースを想定したものです。今回は利用しません。

 また、結果を示すデータはリスト4のように定義しています。このように結果を示すデータクラスを定義した方が、画面と処理が密連携にならずに済みます。

[リスト4] 結果を示すデータ定義クラス(lib/data/Response.dartの抜粋)
class Response{
    final bool _ok;
    final int _code;
    final String _message;

    Response(this._ok, this._code) : _message = '';
    Response.error(this._code,this._message) : _ok = false;

    String get message => _message;
    int get code => _code;
    bool get ok => _ok;
    // : (省略)
}

Futureクラスを使った非同期処理の実装

 では、続いてデータ連携・処理部分を実装していきます。ただし、今回は、実際にサーバにリクエストをしないモックでの実装です。

 実際にサーバにリクエストする場合では、結果が非同期型になります。そのため、モックでも非同期型で結果が返ってくるようにしなければなりません。そのような場合に表1で示すFutureクラスのメソッドが利用できます。

表1:Futureクラスが提供する非同期処理の種類
メソッド名 説明
value 非同期で返す値を設定するメソッド
delayed 一定時間の待ち時間のあとに処理をするメソッド
sync 非同期で行う処理を定義するメソッド。valueではなく関数内で結果を返すようにするメソッド
error エラーを返すためのメソッド

 これらのメソッドを使ったモック実装例がリスト5のようになります。

[リスト5]モックでのデータ連携・処理クラス(lib/controller/MockLoginController.dartの抜粋)
class MockLoginController extends ILoginController{
    // (1) ログイン処理
    @override
    Future login(String loginId, String password) {
        return loginFalseWithDuration(loginId, password);
    }

    // (2) valueの使い方
    Future loginFalse(String loginId,String password){
        return Future.value(Response.error(500, 'ログインIDまたはパスワードを確認してください'));
    }

    // (3) delayedの使い方
    Future loginTrueWithDuration(String loginId,String password){
        return Future.delayed(const Duration(seconds: 1),(){
            return Response(true,200);
        });
    }
    // (4) syncをの使い方
    Future loginSync(String loginId,String password){
        return Future.sync((){
            print("実行中");
            return Response.error(500, 'ログインIDまたはパスワードを確認して下さい');
        });
    }

    // (5) errorの使い方
    Future loginError(String loginId,String password){
        return Future.error(Error());
    }
}

 (1)はILoginControllerのlogin処理の実装です。実際にさまざまな動作を確認するためにはこのメソッド内で(2)~(5)までのように返す結果を変えることを想定しています。

 非同期での結果を返す最も単純な方法は(2)のvalueメソッドを利用する方法です。valueメソッドの引数に値を設定すれば、その値が非同期で返却されるようになります。

 また、実際の非同期処理ではある程度、時間がかかってしまう場合があります。今回の画面の例でもそのためにローディング画面を用意しました。その画面を確認するためにはある程度時間をかけて処理を実行する必要があります。

 そのような場合に利用できるのが(3)のdelayedメソッドです。このメソッドでは、待ち時間を第1引数に、そして、第2引数に結果を返す関数を定義します。また、(4)のsyncメソッドは非同期で処理をするためのメソッドです。

 今回のサンプル上ではあまり、利用しなければいけないケースはありませんが、返す値を作る処理自体が非同期処理内で記述する必要があるケースもあります。

 また、今回のサンプルでは値を返していますが、必ずしも値を返す必要はありません。そのため、これらのメソッドは、画面をロックしないように何らかの処理が必要な場合にも利用されることがあります。

 非同期処理の中でエラーが発生したことと同じようにするのが、(5)のerrorメソッドです。実際に画面内などでエラー処理をする場合には、リスト6のコードでエラー処理を行います。

[リスト6]非同期処理中に生じたエラー処理をする方法
// Futureクラスを使った場合
var f = _pageController.config();
f.catchError((error){
    // エラー処理
});

// awaitキーワードを使った場合
try {
    Response res = await _pageController.login(id,pswd);
} on Error catch(e){
    // エラー処理
};

まとめ

 スマホアプリを開発する際に筆者が最も面倒に感じるのが、外部サービスとの連携部分です。すべての開発者が常に同じように外部サービスを使う上で、何の制限もなく利用できるのであればまだ問題は小さいかも知れません。

 しかし、実際には、そのようなケースはほとんどなく、さまざまな制限が多く発生する場合の方が多いでしょう。そのため、アプリを開発する際には、画面の動作を確認するためと外部サービスも含めた動作で別に確認できる必要があります。

 また、データ操作を含む多くの処理が非同期になってしまいます。今回のログイン画面のように常に画面操作ができることが望ましくないケースもあり、利用者の画面操作を抑制したほうがいい場合もあります。

 このようにデータ連携・操作をする場合には、その目的にあった画面処理も必要になるので、処理の実現方法だけではなく、その処理をしている最中に、利用者側で何ができて、何ができないかを常に考慮する必要があります。

 次回は、実際にサーバにhttpリクエストをする方法を紹介します。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
Flutterで始めるモバイルアプリ開発連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

WINGSプロジェクト について> 有限会社 WINGSプロジェクト が運営する、テクニカル執筆コミュニティ(代表 ...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/16138 2022/09/05 17:06

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー