序章

アプリケーションは、POSTGETおよびその他のHTTPリクエストを頻繁に実行する必要があります。

Flutterは、HTTPリクエストの作成をサポートするhttpパッケージを提供します。

この記事では、httpパッケージを使用してHTTPリクエストを実行し、プレースホルダー情報を表示するFlutterアプリの例を作成します。

前提条件

このチュートリアルを完了するには、次のものが必要です。

  • Flutterをダウンロードしてインストールするには。
  • Android StudioまたはVisual StudioCodeをダウンロードしてインストールするには。
  • コードエディタ用のプラグインをインストールすることをお勧めします。 AndroidStudio用にインストールされたFlutterおよびDartプラグイン。 VisualStudioCode用にインストールされたFlutter拡張機能。

このチュートリアルは、Flutter v1.22.2、Android SDK v30.0.2、およびAndroidStudiov4.1で検証されました。

ステップ1—プロジェクトの設定

セットアップを実行するために、Flutterアプリの例を作成します。

Flutter用に環境を設定したら、次のコマンドを実行して新しいアプリケーションを作成できます。

  1. flutter create flutter_http_example

新しいプロジェクトディレクトリに移動します。

  1. cd flutter_http_example

flutter createを使用すると、ボタンがクリックされた回数を表示するデモアプリケーションが作成されます。

コードエディタでpubspec.yamlを開き、次のプラグインを追加します。

pubspec.yaml
dependencies:
  flutter:
    sdk: flutter

  http: ^0.12.0+2

これはdart.devによって公開された公式のFlutterプラグインであり、 100 % he althスコアを持っているため、このプラグインの信頼性を信頼できます。

ステップ2—GETリクエストの処理

最初のタスクは、APIとの対話に使用できるクラスを作成することです。

コードエディタを開き、libディレクトリにhttp_service.dartファイルを作成します。 ここでは、新しいHttpServiceクラスを開発し、getPosts関数を追加します。

lib / http_service.dart
import 'dart:convert';
import 'package:http/http.dart';
import 'post_model.dart';

class HttpService {
  final String postsURL = "https://jsonplaceholder.typicode.com/posts";

  Future<List<Post>> getPosts() async {
    Response res = await get(postsURL);

    if (res.statusCode == 200) {
      List<dynamic> body = jsonDecode(res.body);

      List<Post> posts = body
        .map(
          (dynamic item) => Post.fromJson(item),
        )
        .toList();

      return posts;
    } else {
      throw "Unable to retrieve posts.";
    }
  }
}

この例では、JSONプレースホルダーに接続します。 このコードは、postsURL文字列でhttpパッケージのgetを使用します。

そのリクエストが成功した場合、このコードはPost.fromJsonを使用してList<Post>を返します。 それ以外の場合は、エラーメッセージがスローされます。

ノート: HTTPステータスコード are used to determine if a request was successful or unsuccessful. A status code of 200 represents a successful HTTP request.

次に、コードエディタを使用して、libディレクトリにpost_model.dartファイルを作成します。 ここでは、新しいPostクラスを開発します。

lib / post_model.dart
import 'package:flutter/foundation.dart';

class Post {
  final int userId;
  final int id;
  final String title;
  final String body;

  Post({
     this.userId,
     this.id,
     this.title,
     this.body,
  });

  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      userId: json['userId'] as int,
      id: json['id'] as int,
      title: json['title'] as String,
      body: json['body'] as String,
    );
  }
}

JSONプレースホルダーからの応答をシリアル化するために、このコードは、JSONMapに基づくfromJsonメソッドを使用して新しいPostを返します。

注:実稼働アプリケーションでは、 json_serializable のようなパッケージを使用して、シリアル化を自動的に処理できます。

JSONプレースホルダーによって返されるPostは、userIdidtitle、およびbodyで構成されます。

手順3—Postsを表示する

次に、コードエディタを使用して、libディレクトリにposts.dartファイルを作成します。 ここでは、HTTPリクエストからJSONプレースホルダーに返されるPostsを表示するPostsPageクラスを作成します。

lib / posts.dart
import 'package:flutter/material.dart';
import 'http_service.dart';
import 'post_model.dart';

class PostsPage extends StatelessWidget {
  final HttpService httpService = HttpService();

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Posts"),
      ),
      body: FutureBuilder(
        future: httpService.getPosts(),
        builder: (BuildContext context, AsyncSnapshot<List<Post>> snapshot) {
          if (snapshot.hasData) {
            List<Post> posts = snapshot.data;
            return ListView(
              children: posts
                  .map(
                    (Post post) => ListTile(
                      title: Text(post.title),
                      subtitle: Text("${post.userId}"),
                    ),
                  )
                  .toList(),
            );
          } else {
            return Center(child: CircularProgressIndicator());
          }
        },
      ),
    );
  }
}

このコードは、FutureBuilderウィジェットを使用して、getPosts()関数と対話します。 これにより、コードはList<Post>の準備ができたことを判断し、それに応じて動作することができます。

snapshot.hasDatafalseの場合、CircularProgressIndicatorが表示されます。 それ以外の場合は、投稿情報付きのListTileが表示されます。

これまでの内容を確認するには、main.dartのコードを置き換える必要があります。

コードエディタでlib/main.dartを開き、PostsPageを使用するように変更します。

lib / main.dart
import 'package:flutter/material.dart';
import 'posts.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'HTTP',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: PostsPage(),
    );
  }
}

コードをコンパイルして、エミュレーターで実行します。

Screenshot of the current state of the application displaying a list of post titles and user ids returned by JSON Placeholder

JSONプレースホルダーによって返される投稿のタイトルとユーザーIDのリストを確認する必要があります。

注:タイトルは、プレースホルダーテキストとして頻繁に使用される LoremIpsumからの抜粋です。

次のステップは、ユーザーが投稿のタイトルをクリックしたときに、投稿に関する詳細情報を含む詳細ページを作成することです。

手順4—PostDetailを表示する

ユーザーが投稿をタップした場合、アプリはユーザーをPostDetailページに移動する必要があります。

コードエディタを使用して、libディレクトリにpost_detail.dartファイルを作成します。 ここでは、個々のPostを表示するPostDetailクラスを作成します。

lib / post_detail.dart
import 'package:flutter/material.dart';
import 'post_model.dart';

class PostDetail extends StatelessWidget {
  final Post post;

  PostDetail({ this.post});

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(post.title),
      ),
      body: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.all(12.0),
          child: Column(
            children: <Widget>[
              Card(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    ListTile(
                      title: Text("Title"),
                      subtitle: Text(post.title),
                    ),
                    ListTile(
                      title: Text("ID"),
                      subtitle: Text("${post.id}"),
                    ),
                    ListTile(
                      title: Text("Body"),
                      subtitle: Text(post.body),
                    ),
                    ListTile(
                      title: Text("User ID"),
                      subtitle: Text("${post.userId}"),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      )
    );
  }
}

このコードは、titleidbody、およびuserIdを表示します。

これまでの状況を確認するには、posts.dartを変更してpost_detail.dartをサポートする必要があります。

lib / posts.dart
import 'package:flutter/material.dart';
import 'http_service.dart';
import 'post_detail.dart';
import 'post_model.dart';

class PostsPage extends StatelessWidget {
  final HttpService httpService = HttpService();

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Posts"),
      ),
      body: FutureBuilder(
        future: httpService.getPosts(),
        builder: (BuildContext context, AsyncSnapshot<List<Post>> snapshot) {
          if (snapshot.hasData) {
            List<Post> posts = snapshot.data;
            return ListView(
              children: posts
                  .map(
                    (Post post) => ListTile(
                      title: Text(post.title),
                      subtitle: Text("${post.userId}"),
                      onTap: () => Navigator.of(context).push(
                        MaterialPageRoute(
                          builder: (context) => PostDetail(
                            post: post,
                          ),
                        ),
                      ),
                    ),
                  )
                  .toList(),
            );
          } else {
            return Center(child: CircularProgressIndicator());
          }
        },
      ),
    );
  }
}

コードをコンパイルして、エミュレーターで実行します。

Screenshot of the current state of the application displaying the detail of an individual post returned by JSON Placeholder

次のステップは、投稿を削除して削除する機能を追加することです。

ステップ5—DELETEリクエストの処理

HTTPリクエストのもう1つの例は、DELETEメソッドの使用です。

コードエディタでhttp_service.dartに戻り、deletePost(int id)メソッドを作成します。

lib / http_service.dart
import 'dart:convert';
import 'package:http/http.dart';
import 'post_model.dart';

class HttpService {
  final String postsURL = "https://jsonplaceholder.typicode.com/posts";

  // ...

  Future<void> deletePost(int id) async {
    Response res = await delete("$postsURL/$id");

    if (res.statusCode == 200) {
      print("DELETED");
    } else {
      throw "Unable to delete post.";
    }
  }
}

コードエディタでpost_detail.dartに戻り、IconButtonAppBar内のactions配列に追加します。 アイコンを押すと、関連する投稿が削除されます。

lib / post_detail.dart
import 'package:flutter/material.dart';
import 'http_service.dart';
import 'post_model.dart';

class PostDetail extends StatelessWidget {
  final HttpService httpService = HttpService();
  final Post post;

  PostDetail({ this.post});

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(post.title),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.delete),
            onPressed: () async {
              await httpService.deletePost(post.id);
              Navigator.of(context).pop();
            },
          )
        ],
      ),
      // ...
    );
  }
}

コードをコンパイルして、エミュレーターで実行します。

投稿の詳細ページにアクセスすると、AppBarに削除アイコンボタンが表示されます。 ボタンを押すと、コンソールにメッセージが出力されます。

Output
flutter: DELETED

これは削除リクエストを表します。 JSONプレースホルダーとこのサンプルアプリケーションの制限により、投稿は実際には削除されません。

結論

この記事では、Flutterhttpパッケージを操作する方法を学びました。 これにより、投稿のリストをGETし、個々の投稿をDELETEすることができました。

postputpatchなどの同様の操作も使用できます。 詳細については、公式ドキュメントを参照してください。