0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Flutter】APIで取得した内容を画面に表示する方法(毎日Flutter生活17日目)

Posted at

こんにちは!tatata-keshiです:smiley:

16日目の記事で、ChatworkのAPIを利用して自分のプロフィール情報を取得しその内容をコンソール上に表示させました。
今回の記事では取得した内容を画面に表示できるようにカスタマイズしていきます。

1. モデルクラスの作成

始めに、APIで受け取ったデータを格納するモデルクラスを作成していきます。

APIのレスポンスはjson形式で返ってきますが、jsonの中身をモデルクラスに定義することによって型安全になる点や、アプリ内ロジックで再利用しやすくなるといったメリットがあります。

なお、今回使用した自分の情報を取得するAPIのレスポンス形式は以下のようになっています。

{
  "account_id": 123,
  "room_id": 322,
  "name": "John Smith",
  "chatwork_id": "tarochatworkid",
  "organization_id": 101,
  "organization_name": "Hello Company",
  "department": "Marketing",
  "title": "CMO",
  "url": "http://mycompany.example.com",
  "introduction": "Self Introduction",
  "mail": "taro@example.com",
  "tel_organization": "XXX-XXXX-XXXX",
  "tel_extension": "YYY-YYYY-YYYY",
  "tel_mobile": "ZZZ-ZZZZ-ZZZZ",
  "skype": "myskype_id",
  "facebook": "myfacebook_id",
  "twitter": "mytwitter_id",
  "avatar_image_url": "https://example.com/abc.png",
  "login_mail": "account@example.com"
}

今回は表示名とメールアドレス、プロフィール画像を表示させるためこれらの内容をモデルクラスに含みます。

libディレクトリに新たに models ディレクトリを作成し、user.dart を作成します。

lib
  ├── main.dart
+ └── models
+     └── user.dart

作成した user.dart にUserクラスを定義していきます。User クラスのプロパティにはレスポンスの内 namemailavatar_image_url を設定します。

user.dart
class User {
  User({required this.name, required this.loginMail, required this.avatarImageUrl});

  final String name;
  final String loginMail;
  final String avatarImageUrl;

  factory User.fromJson(dynamic json) {
    return User(
      name: json['name'] as String,
      loginMail: json['login_mail'] as String,
      avatarImageUrl: json['avatar_image_url'] as String,
    );
  }
}

次にAPIレスポンスで受け取ったjsonを User クラスに変換するファクトリコンストラクタを作成します。

これが現状の FetchMe メソッドの実装です。

factory User.fromJson(dynamic json) {
  return User(name: json['name'] as String, mail: json['mail'] as String);
}

2. fetchMeメソッドの書き換え

次にAPIを叩いて自分のプロフィールを取得するfetchMeメソッドを書き換えていきます。

前回の記事では受け取ったレスポンスをそのままコンソールに出力していましたが、これをレスポンスからUserクラスを作成し返すメソッドに書き換えていきます。

main.dart
Future<void> fetchMe() async {
  final apiToken = dotenv.env['CW_API_TOKEN'];

  if (apiToken == null || apiToken.isEmpty) {
    debugPrint('CW_API_TOKEN が取得できていません');
    return;
  }

  final uri = Uri.parse('https://api.chatwork.com/v2/me');

  try {
    final res = await http
        .get(
          uri,
          headers: {'X-ChatWorkToken': apiToken, 'Accept': 'application/json'},
        )
        .timeout(const Duration(seconds: 15));

    debugPrint('status: ${res.statusCode}');
    debugPrint('body: ${res.body}');
  } catch (e) {
    debugPrint('ERROR: $e');
  }
}

これを User クラスを返すように変更します。

main.dart
// 返り値をvoidからUserクラスに変更
Future<User> fetchMe() async {
  final apiToken = dotenv.env['CW_API_TOKEN'];

  if (apiToken == null || apiToken.isEmpty) {
    throw Exception('CW_API_TOKEN が取得できていません'); // Exceptionを投げるように変更
  }

  final uri = Uri.parse('https://api.chatwork.com/v2/me');

  final res = await http
      .get(
        uri,
        headers: {'X-ChatWorkToken': apiToken, 'Accept': 'application/json'},
      )
      .timeout(const Duration(seconds: 15));

  // エラーレスポンスが返ってきたらExceptionを投げる
  if (res.statusCode < 200 || res.statusCode >= 300) {
    throw Exception('Request failed: ${res.statusCode} ${res.body}');
  }

  // User.fromJsonを用いてUserクラスを返す
  return User.fromJson(jsonDecode(res.body));
}

3. APIから受け取った値を画面に表示する

元々の実装では、APIを呼び出すボタンウィジェットしか画面に配置しておりませんでした。

ここにレスポンスを受け取るとユーザーの情報を表示するように変更していきます。

main.dart
class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: Home());
  }
}

// StatefulWidgetであるHomeを作成
class Home extends StatefulWidget {
  const Home({super.key});

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  User? user;
  bool isLoading = false;
  String? errorMessage;

  Future<void> onFetch() async {
    setState(() {
      isLoading = true;
      errorMessage = null;
    });

    try {
      final result = await fetchMe();
      setState(() {
        user = result;
      });
    } catch (e) {
      setState(() {
        errorMessage = e.toString();
        user = null;
      });
    } finally {
      setState(() {
        isLoading = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Chatwork API Demo')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            ElevatedButton(
              onPressed: isLoading ? null : onFetch,
              child: Text(isLoading ? '取得中...' : '自分の情報を取得'),
            ),
            const SizedBox(height: 16),

            if (errorMessage != null) ...[
              Text(errorMessage!, style: const TextStyle(color: Colors.red)),
              const SizedBox(height: 16),
            ],

            if (user != null)
              Column(
                spacing: 8,
                children: [
                  CircleAvatar(
                    radius: 40,
                    backgroundImage: NetworkImage(user!.avatarImageUrl),
                  ),
                  Text('name: ${user?.name}'),
                  Text('mail: ${user?.loginMail}'),
                ],
              ),
          ],
        ),
      ),
    );
  }
}

ここまで実装ができたらアプリケーションを実行します。

「自分の情報を取得」ボタンを押すと自分のプロフィール情報がAPIで取得され、画面に表示させることができました。

最新の写真を表示.png

まとめ

今回はChatwork API経由で取得した自分のプロフィール情報をFlutterアプリの画面上に表示させることができました。

外部APIと通信する実装ができるようになり、より実用的なアプリが作れるようになった気がします。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?