LoginSignup
1
2

More than 1 year has passed since last update.

Flutterでアプリを作ろうとして案の定躓いた話

Last updated at Posted at 2021-12-05

FlutterでAPI通信をしてエラーが出て困った話

swiftUIを学習していたのですが、androidのAPPもまとめて作れるということでFlutterを使った話。
まずはAPIでhttps通信しなければいけない気がして、ネットで調べその通りに実装してエラーが出てしまいました。これはそのエラーを解決したお話です。

作ろうとしたもの

ボタンを押すとランダムなユーザー情報を表示するだけの習作App。
出来上がりがこちら。
app_image
使ったAPIはこちら。

http://api.randomuser.me/

画像、名前、性別、電話番号などを取得できるテストするには非常に便利なAPIです(有名ですね)
※responseはjsonです。

コードとエラー内容と解決と

main.dart
  loadData() async {
    String url = 'http://api.randomuser.me/';
    http.Response response = await http.get(url);
    var userData = json.decode(utf8.decode(response.bodyBytes));
    setState(() {
      _gender = userData['results'][0]['gender'];
      _image = userData['results'][0]['picture']['large'];
      _firstName = userData['results'][0]['name']['first'];
      _lastName = userData['results'][0]['name']['last'];
      _country = userData['results'][0]['location']['country'];
      _phone = userData['results'][0]['phone'];
      _email = userData['results'][0]['email'];
    });
    print(userData['results'][0]);
    //jsonの中身を見るだけ
  }

これはAPIのリクエストをして取得したデータをあらかじめ設定しておいたstateにセットする関数を書いたコードです。
これで上手くいくはずなのに、こんなエラーが。

The argument type 'String' can't be assigned to the parameter type 'Uri'

StringをパラメータタイプのUriに設定できない?
よくわからないので公式を調べてみると。。
公式URL→https://pub.dev/packages/http/changelog
どうやらhttps0.13.0(通信に使用しているパッケージです)から仕様に変更があったようでした。
変更内容は
「これまではString型のURLでAPIを叩いてもOKだったけど、これからはURIで叩いてもらっていい?」
と、いった内容でしたので...

main.dart
  loadData() async {
    String url = 'http://api.randomuser.me/';
    http.Response response = await http.get(Uri.parse(url));
    //↑urlをUri.parse()でuriにパースしました。
    var userData = json.decode(utf8.decode(response.bodyBytes));
    setState(() {
      _gender = userData['results'][0]['gender'];
      _image = userData['results'][0]['picture']['large'];
      _firstName = userData['results'][0]['name']['first'];
      _lastName = userData['results'][0]['name']['last'];
      _country = userData['results'][0]['location']['country'];
      _phone = userData['results'][0]['phone'];
      _email = userData['results'][0]['email'];
    });
    print(userData['results'][0]);
    //jsonの中身を見るだけ
  }

と改修しました。
これにはFlutterもニッコリ。無事エラーが消えて解決しました。
そしてコードの全体はこんな感じ↓

main.dart
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ランダムユーザー取得',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'ランダムユーザー取得'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String _gender = "";
  String _firstName = "";
  String _lastName = "";
  String _country = "";
  String _phone = "";
  String _email = "";
  String _image = "http://placehold.jp/08e1f5/ffffff/300x300.png";

  // APIから取ってくる
  loadData() async {
    String url = 'http://api.randomuser.me/';
    http.Response response = await http.get(Uri.parse(url));
    //↑urlをUri.parse()でuriにパースしました。
    var userData = json.decode(utf8.decode(response.bodyBytes));
    setState(() {
      _gender = userData['results'][0]['gender'];
      _image = userData['results'][0]['picture']['large'];
      _firstName = userData['results'][0]['name']['first'];
      _lastName = userData['results'][0]['name']['last'];
      _country = userData['results'][0]['location']['country'];
      _phone = userData['results'][0]['phone'];
      _email = userData['results'][0]['email'];
    });
    print(userData['results'][0]);
    //jsonの中身を見るだけ
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Image.network(
              _image,
              width: 300,
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  'User Name :',
                  style: TextStyle(color: Colors.blue, fontSize: 20),
                ),
                Text(
                  _firstName,
                  style: const TextStyle(fontSize: 30),
                ),
                const Text(
                  " ",
                  style: TextStyle(fontSize: 30),
                ),
                Text(
                  _lastName,
                  style: const TextStyle(fontSize: 30),
                ),
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  "Gender :",
                  style: TextStyle(color: Colors.blue, fontSize: 20),
                ),
                Text(
                  _gender,
                  style: const TextStyle(fontSize: 30),
                ),
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  "Country :",
                  style: TextStyle(color: Colors.blue, fontSize: 20),
                ),
                Text(
                  _country,
                  style: const TextStyle(fontSize: 30),
                ),
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  "E-Mail :",
                  style: TextStyle(color: Colors.blue),
                ),
                Text(
                  _email,
                  style: const TextStyle(fontSize: 20),
                ),
              ],
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  "Phone :",
                  style: TextStyle(color: Colors.blue, fontSize: 20),
                ),
                Text(
                  _phone,
                  style: const TextStyle(fontSize: 30),
                ),
              ],
            ),
            ElevatedButton(
              onPressed: () => {loadData()},
              child: const Text("ユーザー情報更新"),
            )
          ],
        ),
      ),
      // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

感想

Dartってどこか知ってる雰囲気だったのですが、調べるとJavaScriptの後継的な言語とのことでした。
出来上がったアプリはどことなくマッチングアプリっぽくなりました。
今回のアプリはUIがまだまだですが、目的であるAPIを叩いて情報を取得、表示させることができたので無問題です。
次は入力情報によってAPIリクエストを送ったり、端末自体の機能にアクセスする機能も実装していきます。
新しい技術は仕様変更も多く、これまではOKだったのにエラーになったりするので公式ドキュメントは大事やでと思いました。

1
2
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
1
2