Android Studio をやめて、VSCode で Flutter アプリを作ってみる

# 背景

娘が Scratch Jr. で楽しんでいたの、パパも頑張っちゃうぞーという気分になって
Android Studio でなんかアプリ作ってみようって思った記録 その２

kotlin だろと思って始めたけど、同僚にそそのかされて Flutter に切り替えた
以下が前回

https://qiita.com/baku2san/items/49260a8292ccfcf61247

# 躓き記録 on Flutter with VSCode

https://docs.flutter.dev/get-started/codelab

まずは、この通りにやってみる

https://codelabs.developers.google.com/codelabs/flutter-codelab-first?hl=ja&authuser=1#2

特に躓くこともなく、なるほどなるほど、と完了。

で、ここまできたら、娘が最近頑張ってる九九計算アプリでも作ってみるかと思いベースを変更



## android 用 build でエラー
```powershell
BUILD FAILED in 4s

┌─ Flutter Fix ────────────────────────────────────────────────────────────────────────────────────┐
│ [!] This is likely due to a known bug in Android Gradle Plugin (AGP) versions less than 8.2.1,   │
│ when                                                                                             │
│   1. setting a value for SourceCompatibility and                                                 │
│   2. using Java 21 or above.                                                                     │
│ To fix this error, please upgrade your AGP version to at least 8.2.1. The version of AGP that    │
│ your project uses is likely defined in:                                                          │
│ {project}\android\settings.gradle,                                        │
│ in the 'plugins' closure (by the number following "com.android.application").                    │
│  Alternatively, if your project was created with an older version of the templates, it is likely │
│ in the buildscript.dependencies closure of the top-level build.gradle:                           │
│ {project}\android\build.gradle,                                           │
│ as the number following "com.android.tools.build:gradle:".                                       │
│                                                                                                  │
│ For more information, see:                                                                       │
│ https://issuetracker.google.com/issues/294137077                                                 │
│ https://github.com/flutter/flutter/issues/156304                                                 │
└──────────────────────────────────────────────────────────────────────────────────────────────────┘
Error: Gradle task assembleDebug failed with exit code 1

Exited (1).
```

対処は、説明にあるように、以下バージョンを修正
>     id "com.android.application" version "8.1.0" apply false

>     id "com.android.application" version "8.3.0" apply false

で、別のエラー 
```powershell
 Where:
Build file '{project}\android\app\build.gradle' line: 2

* What went wrong:
An exception occurred applying plugin request [id: 'com.android.application']
> Failed to apply plugin 'com.android.internal.version-check'.
   > Minimum supported Gradle version is 8.4. Current version is 8.3. If using the gradle wrapper, try editing the distributionUrl in {project}\android\gradle\wrapper\gradle-wrapper.properties to gradle-8.4-all.zip

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

BUILD FAILED in 17s
Error: Gradle task assembleDebug failed with exit code 1
```

で、8.3 を 8.4 にしてみる
>     distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip

>     distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip

で、反映？

```powershell
flutter clean
flutter pub get
```
再度エラー

```powershell
Launching lib\main.dart on SO 51A in debug mode...
Warning: SDK processing. This version only understands SDK XML versions up to 3 but an SDK XML file of version 4 was encountered. This can happen if you use versions of Android Studio and the command-line tools that were released at different times.
Could not write file to {project}\build\app\intermediates\flutter\debug\flutter_assets\shaders/ink_sparkle.frag

Target debug_android_application failed: PathExistsException: Cannot copy file to '{project}\build\app\intermediates\flutter\debug\flutter_assets\fonts/MaterialIcons-Regular.otf', path = 'C:\flutter\bin\cache\artifacts\material_fonts\MaterialIcons-Regular.otf' (OS Error: ���ɑ��݂���t�@�C�����쐬���邱�Ƃ͂ł��܂���B
, errno = 183)
2

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:compileFlutterBuildDebug'.
> Process 'command 'C:\flutter\bin\flutter.bat'' finished with non-zero exit value 1

```

単に、色々やってる際に、<code>build</code> 以下のファイルを開いてしまっていた為に、build 時に更新出来ずに失敗しただけだった。
ということで、ファイルを閉じたら、問題なく、android 上で起動！！ :haircut: 

## android でのデバッグは？

開発者モードで、USB/wifi デバッグを有効化する。

最初反応しなくて悩んでたら、充電専用ケーブルで繋げていたという落ち :sweat: 

接続したかの確認

```powershell: console で
flutter devices
```

Android でのデバッグを接続
<code>CTRL+SHIFT+P</code> で デバッグ機器選択
> Flutter: Select Device


## 永続化は？

1. local: ex.) shared_preferences
1. local db: ex.) sqflite 
1. cloud: ex.) cloud_firestore (firebase) 

shared_preferences　でやってみる

https://docs.flutter.dev/get-started/fundamentals/local-caching#caching-data-with-shared_preferences

```dart: save & load
  void loadScores() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    List<String>? savedScores = prefs.getStringList('scores');

  }

  Future<void> saveScores() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    (...)    
    await prefs.setStringList('scores', savedScores);
  }
```

## DateTime をフォーマットしたい

intl パッケージを入れてフォーマットするらしい

```dart: DateTime format
import 'package:intl/intl.dart';

DateFormat('yyyy-MM-dd HH:mm').format(score.datetime.toLocal()),
```

```yaml: pubspec.yaml
dependencies:
  intl: ^0.20.1
```

## ../../AppData/Local/Pub/Cache/hosted/pub.dev/fl_chart-0.50.6/lib/src/utils/utils.dart:254:20: Error: Member not found: 'MediaQuery.boldTextOverride'. if (MediaQuery.boldTextOverride(context)) {

fl_chart を入れたところ、どうやら、依存関係に問題が？

ということで、

```powershell: clean & 更新
flutter clean
flutter pub get
```

ただ、この後、大量のエラーが出て何事？ってなった
- import 自体が赤線惹かれたり
   > Target of URI doesn't exist: 'package:flutter/widgets.dart'. Try creating the file referenced by the URI, or try using a URI for a file that does exist.darturi_does_not_exist

- widget 自体もダメ
   > Undefined name 'WidgetsFlutterBinding'. Try correcting the name to one that is defined, or defining the name.dartundefined_identifier

結局以下が上手くいってなかっただけっぽい。再度実行したら解決した
```powershell:  更新
flutter pub get
```

と思ったけれど、build すると同一エラーってことで、<code>fl_chart</code> を最新化して解決

<code> flutter pub outdated</code> で最新バージョンを調べて以下指定して、再度 <code>flutter pub get</code>

```fluent: pubspec.yaml
dependencies:
  fl_chart: ^0.69.0
```


## 最終的に Android 12 向けにするとしたら？

android studio だと、ターゲットを決めていたが、flutter では、build 対象として定義するだけで、flutter 自体の制約はない？
ここは、実際にデプロイする際に再検討かもね

```gradle: BarRodData
android {
    compileSdkVersion 31 // Android 12

    defaultConfig {
        applicationId "com.example.app"
        minSdkVersion 21 // 必要に応じて調整
        targetSdkVersion 31 // Android 12
        versionCode 1
        versionName "1.0"
    }
}
```
## The argument type 'SideTitles' can't be assigned to the parameter type 'AxisTitles?'. dartargument_type_not_assignable

fl_chart ライブラリのバージョンが更新されたため

SideTitles -> AxisTitles
```fluent: SideTitles
leftTitles: SideTitles(showTitles: true),
```
```fluent: AxisTitles
leftTitles: AxisTitles(
  sideTitles: SideTitles(showTitles:   true),
),
```

## The method 'BarRodData' isn't defined for the type 'ScorePage'. Try correcting the name to the name of an existing method, or defining a method named 'BarRodData'.dartundefined_method

BarRodData から BarChartRodData に変更

```fluent:
BarRodData(
    toY: score.score.toDouble(),
    color: Colors.blue,
),
```

```fluent: 
BarChartRodData(
    toY: score.score.toDouble(),
    color: Colors.blue,
),
```

## Try flutter pub outdated for more information

古いバージョンがあったので、更新

```powershell: update
flutter pub upgrade --major-versions
```

## State 管理はどうしたらいい？

react component みたいにして、各 widget に閉じ込めて、state 変化で発火させる感じかな
AppState にガンガン追加しちゃうと、再描画が増えて重くなりそうかな。まぁ、普通のアプリじゃそれほど影響はないんだとは思うけど。理解して実践を試すのは大切よね

# あとがき

無事、Android 上でデバッグできるまで辿り着いた :sweat_smile: 

あとは、娘に触ってもらって・・かな