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備忘録

Posted at

はじめに

Udemyで習った内容の備忘録のためのものです.

到達目的

  • 例外や失敗時のための処理の仕方
  • 使用した関数の理解

内容

下記が理解したいコードです,郵便番号のAPIの実装のためのコードです.

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

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  TextEditingController controller = TextEditingController();
  List<String> items = [];
  String errorMessage = '';

  Future<void> loadZipCode(String zipCode) async {
    setState(() {
      errorMessage = 'APIレスポンス待ち';
    });

    final response = await http.get(
        Uri.parse('https://zipcloud.ibsnet.co.jp/api/search?zipcode=$zipCode'));

    if (response.statusCode != 200) {
      // 失敗
      return;
    }
    //成功
    final body = json.decode(response.body) as Map<String, dynamic>;
    final results = (body['results'] ?? []) as List<dynamic>;

    if (results.isEmpty) {
      setState(() {
        errorMessage = 'そのような郵便番号の住所はありません';
      });
    } else {
      setState(() {
        errorMessage = '';
        items = results
            .map((result) =>
                "${result['address1']}${result['address2']}${result['address3']}")
            .toList(growable: false);
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: TextField(
          controller: controller,
          keyboardType: TextInputType.number,
          onChanged: (value) {
            if (value.isNotEmpty) {
              loadZipCode(value);
            }
          },
        ),
      ),
      body: ListView.builder(
        itemBuilder: (context, index) {
          if (errorMessage.isNotEmpty) {
            return ListTile(title: Text(errorMessage));
          } else {
            return ListTile(title: Text(items[index]));
          }
        },
        itemCount: items.length,
      ),
    );
  }
}

1.MyAppWidget

MyApp

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

main関数に呼び出されるルートWidgetで,このWidgetで宣言されたものから実行されていく.最初に渡す引数やUI構築のための変数などもここで宣言される

解釈

アプリケーションを構築するための最初のWidgetで初期設定などここで設定する.

2. MyhomePageウィジェット

MyhomePage

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  TextEditingController controller = TextEditingController();
  List<String> items = [];
  String errorMessage = '';
	....
}

上記のコードについて, MyAppで呼び出されるなウィジェット.ここで変化する対象である変数やウィジェットを宣言する.

3. loadZipCode関数

loadZipCode

Future<void> loadZipCode(String zipCode) async {
  setState(() {
    errorMessage = 'APIレスポンス待ち';
  });

  final response = await http.get(
      Uri.parse('https://zipcloud.ibsnet.co.jp/api/search?zipcode=$zipCode'));

  if (response.statusCode != 200) {
    // 失敗
    return;
  }
  //成功
  final body = json.decode(response.body) as Map<String, dynamic>;
  final results = (body['results'] ?? []) as List<dynamic>;

  if (results.isEmpty) {
    setState(() {
      errorMessage = 'そのような郵便番号の住所はありません';
    });
  } else {
    setState(() {
      errorMessage = '';
      items = results
          .map((result) =>
              "${result['address1']}${result['address2']}${result['address3']}")
          .toList(growable: false);
    });
  }
  

上記の内容についてわからない単語がちょくちょく出てきたので,下記にまとめました.

項目 内容 解釈
Future 非同期プログラミング.操作が完了した場合のみ通知し,値は返さない関数 成功したら通知のみしてくれるvoid関数
async & await 非同期プログラミングのための処理.特定タスクの完了を待たずに実行させることを目的としている. asyncは非同期関数であることの宣言.awaitはどの処理を待つかを宣言するためのもの
dynamic any型 どんな変数でも行ける.しかし,どんな値をコンパイラ時点で扱うのかはわからない

5. Buildメソッド

loadZipCode

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: TextField(
        controller: controller,
        keyboardType: TextInputType.number,
        onChanged: (value) {
          if (value.isNotEmpty) {
            loadZipCode(value);
          }
        },
      ),
    ),
    body: ListView.builder(
      itemBuilder: (context, index) {
        if (errorMessage.isNotEmpty) {
          return ListTile(title: Text(errorMessage));
        } else {
          return ListTile(title: Text(items[index]));
        }
      },
      itemCount: items.length,
    ),
  );
}
  

上記のコードが基本的なUIについての内容です.TextFiledがテキストを読み込むためのUIで,ListViewがAPI通信で得た内容の表示のためのコードです.
itemCount: items.length,はListViewのための引数です.ListViewのアイテム表示をいくつするかを表したものです.

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?