🏄

Flutter & ChatGPT モバイルアプリ開発(1)

2024/02/09に公開

はじめに

業務ではPHPでwebサイトの構築を行っています。最近は書くコード量が減ってしまいましたが、本職はRubyエンジニアです。

PhpStormやRubyMineやPyCharmでGitHub Copilotのお世話になりながら、コメントを書いて改行してコードが表示されたらタブを押す毎日。何か疑問があったらChatGPTに質問してしまい、ググって読んで考えるということができなくなりつつあります。

こんな怠惰な生活を送っている中でふとGTP-4だけでどこまで開発が可能なのか試してみようと思い作り始めたアプリの作業記録がこの投稿です。もっとも一から仕様を考えるのは面倒困難だったので、日々お世話になっている専ブラをパクリ眺めながら着手しました。

とりあえずの目標は、【カテゴリ一覧】⇔【板一覧】⇔【スレ一覧】⇔【レス一覧】の遷移。アニメーションでスライドイン、スライドアウトすること、左から右へのフリックで画面が一つ前に戻ることまでを考えていました。

ちなみにFlutterもdartもまったく知りません。あえてフレームワークも言語も仕様をまったく勉強せずにChatGPTに丸投げするというのがコンセプトです。

作業開始

最初はこんな感じでスタートしました。

  • flutterでmain.dartを作成してください。処理の内容は、 https://menu.5ch.net/bbsmenu.json からJSONを読み込み、それを表示するというものです。
  • JSONの内容のエンコーディングはUTF-8です。表示が文字化けしているので修正してください。

できあがったのがこちら。

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: JsonFetchPage(),
    );
  }
}

class JsonFetchPage extends StatefulWidget {
  
  _JsonFetchPageState createState() => _JsonFetchPageState();
}

class _JsonFetchPageState extends State<JsonFetchPage> {
  String _data = '';

  
  void initState() {
    super.initState();
    _fetchData();
  }

  Future<void> _fetchData() async {
    final response = await http.get(Uri.parse('https://menu.5ch.net/bbsmenu.json'));

    if (response.statusCode == 200) {
      setState(() {
        // 明示的にUTF-8でデコード
        _data = utf8.decode(response.bodyBytes);
      });
    } else {
      setState(() {
        _data = 'Failed to load data';
      });
    }
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('JSON Fetch Example'),
      ),
      body: SingleChildScrollView(
        child: Padding(
          padding: EdgeInsets.all(16.0),
          child: Text(_data),
        ),
      ),
    );
  }
}

このコードを見たときにキレイだ、見た目がいいと感じました。もっとも、型が前にあってカーリーブラケットが右端で開いて左端で閉じてくれてたらそれだけでいいんですけどね。スムーズに読めるオーソドックスな見た目というのはとても大事だと思います。

こんな感じで動きました。

引き続き注文を投げ続けます。

  • 取得したJSONにはmenu_listというプロパティがあり、配列を持っています。配列内の各オブジェクトにはcategory_nameというプロパティがあり文字列をもっています。このcategory_nameの一覧をリスト形式で表示してください。
  • うまくリストが表示されましたが間隔が開きすぎているようです。行間が一行空いているのでしょうか?行間を詰め、横に2列で表示してください。表示はリストの先頭から左右左右…としてください。
  • 各カテゴリ名がとても大きな矩形の中央に表示されています。通常の文字のリストとして表示することはできないのでしょうか?
  • 一行に2列で表示してください。矩形で囲む必要はありません。横方向に半分ずつのスペースを使ってください。
  • 行間を詰めることはできませんか?
  • 各項目の間に細いグリッド線を引くことはできますか?外側には線は不要です。上下、左右のアイテム間だけにしてください。
  • とてもよい感じです。最初の行は上側にも線を引いてください。
  • それぞれのカテゴリ名をタップすると次の画面に移動するようにしてください。次の画面は右からスライドして現れるようにしてください。次も同様のリスト画面ですが、ここではまだ空のままでかまいません。内容は各カテゴリに含まれる板の一覧(board list)となる予定です。
  • BoardListPageは別のファイルにできますか?
  • Androidではスライドインのアニメーションが動作しないようです。これは仕様でしょうか?iPhoneでは動作しています。
  • 以下の行で"Invalid use of a private type in a public API."という警告が発生しています。修正可能でしょうか?
_JsonFetchPageState createState() => _JsonFetchPageState();

コピペした瞬間にホットリロードされて即座に動作チェックできるのは本当にありがたいことです。とりあえずbbsmenuを読んでカテゴリ一覧をグリッド表示し、カテゴリ名をクリックすると右からスライドインしてくるところまでできました。

板一覧は仮ページです。フリックもできません。ここまで90分ほどでしょうか。

仕様を考えて投げ込むだけでここまできれいに整った品質の良いコードが出てくるなら、コードを書く、書けるということの相対的なポジションが下がっていきますね。まだまだ言うことを聞いてもらうには手間がかかりますし、できあがったコードを念のために確認する必要はありますが。

仕様をいかに言語化して伝えられるかがすべての世界になって行くのでしょうか。

今回のまとめ

ここまでのコードです。
https://github.com/yasuda0320/SurfBrett/tree/day0001/lib

10ファイルでそれなりのサイズになりましたね。すべてChatGPTからのコピペです。概算ですが20時間くらいでしょうか。こんなの一からFlutterとdartを勉強して自力で書いたら何ヶ月かかることか。GPT-4バンザイ!

続きはこちら。
https://zenn.dev/nori/articles/403df964f5c6e3

React Native版はこちら。
https://zenn.dev/nori/articles/80aeecb010dcd2

Discussion