Open22

Flutter実践入門 | サポートサイト/読者コミュニティ

kazutxtkazutxt

本ページは「Flutter実践入門」のサポートサイト/読者コミュニティです。
https://zenn.dev/kazutxt/books/flutter_practice_introduction

本の感想や誤字/脱字/リンク切れなどがございましたら、ご気軽にコメント頂ければと思います!!

また、最近こんなものが流行っている/こんなテーマが読みたいというものをコメント頂ければ、執筆を検討したいと思います。

テクニカルな部分や掲載ソースコードで再現不可なども対応させて頂きますが、執筆時と前提が変わっていたり、環境が再現できないものもございますので、基本的には書籍内容に対するご支援とさせて頂きます。

Yutaka KubotaYutaka Kubota

細かくて恐縮です。 typoと思われる箇所を見つけてしまったのご報告します。

Chapter 05 チュートリアル編3:HelloWorldと基本構成の プログラムの基本構成 において

途中StateFulWidgetPを継承した

StateFulWidgetPStateFulWidget

kazutxtkazutxt

ご報告ありがとうございます。
ご指摘通り、typoでしたの修正いたしました。

Gekitenius.YGekitenius.Y

Dartのアップデートの影響でエラーが出てしまう箇所があったのでお知らせします。

エラー箇所
初級編4:テスト(Unit/Widget/Integration)>Integrationテスト
https://zenn.dev/kazutxt/books/flutter_practice_introduction/viewer/beginner_test

解消
Null Safety有効化時のUnit Test
https://qiita.com/nukotsuka/items/66236723bf17c4574608
変数 driver 宣言時にlateをつけると直りました
FlutterDriver driver;
late FlutterDriver driver;

kazutxtkazutxt

ご報告ありがとうございます。
ご指摘の通り、該当チャプターはNullSafety導入前に執筆された部分だったため、修正をさせていただきました。

また、本書が全般的に他の部分でも執筆タイミングの関係で、最新版では動作しない可能性があるため、注意喚起のページとNon-nullable by default(NNBD)が問題だった場合に、問題を解決しやすいように追加ページに情報を記載することにしました。
https://zenn.dev/kazutxt/books/flutter_practice_introduction/viewer/meta_attention

am10am10

めっちゃお世話になってます!
こちらのローカライズの部分 jp ではなく ja ではないでしょうか?

     supportedLocales: [
       const Locale('jp', ''), //日本語
       const Locale('en', ''), //英語
     ],

https://zenn.dev/kazutxt/books/flutter_practice_introduction/viewer/intermediate_localization#手順6-アプリでの利用

kazutxtkazutxt

ご報告ありがとうございます!
ご指摘の通り、jpではなくjaの誤記でした。
先程、修正をしてチャプターを更新させていただきました。

たくみんたくみん

説明がとてもわかりやすいので、毎日読んで勉強させていただいています
ありがとうございます!

1点、気になった箇所があったのでお知らせします

Chapter 08 チュートリアル編5:Dartの基本にあるメソッドの名前付きパラメタについての説明ですが
method1(param: 1, param2: "data")ではなくmethod1({param1, param2})ではないでしょうか?

名前付きかつデフォルトパラメタにする場合はmethod1({param = 1, param2 = 'data'})のようになると思います!

よろしくお願いします!

kazutxtkazutxt

いつもご利用ありがとうございます。

ご連絡ありがとうございます。
該当箇所は、関数定義と関数呼び出しが混ざって記載されており、大変わかりづらく誤解を招く内容となっておりました。
そこで、それぞれ関数定義と関数呼び出しの例を載せたスニペットを掲載することにしました。

waku112358waku112358

勉強させていただいています。ありがとうございます。

Part5-4 IntefitedWidget についてです。

ほぼ重複なので省略しますが、WidgetAとMyInheritedWidgetのString messageをint counterに変更

ということでしたので、String messageint counterと修正して動かしてみたところ、以下のエラーとなりました。

WidgetAのbuild()の

Widgets.dart
MyInheritedWidget _myInheritedWidget = MyInheritedWidget.of(context);

MyInheritedWidget.dart
static MyInheritedWidget of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>() as MyInheritedWidget;
// type 'Null' is not a subtype of type  'MyInheritedWidget' in type cast

と、ツリーの親にMyInheritedWidgetがいないため?Nullになっているのだと思いますが、
具体的にどう修正すると値を変えない例となるのかがわからず。。。助言いただけるとありがたいです。

kazutxtkazutxt

ご連絡ありがとうございます。
まず、頂いたエラー事象を再現することができました。

結論といたしましては、ご指摘/ご認識の通り。値を変えない例のmain.dartのソースコード例の中に、MyInheritedWidgetが存在せず、Widgetツリーを遡ってもMyInheritedWidgetが見つからずnullが返却されるという事象が発生しておりました。
※改定の過程で抜け落ちたものと思われます。申し訳ございません。

取り急ぎ、先程「上級編4:InheritedWidget」のページを更新し、Scaffoldの上位にMyInheritedWidgetを入れエラーが出ないように修正いたしました。

※エラー自体は、上記対応で回避できるものの、最適化やわかりやすさなどには改善の余地があると考えておりますので、次回以降の改定時に検討させていただきます。

tetsuyaiwbctetsuyaiwbc

IoT系のハードを作ることが多いのですが、BLEでスマホと連携することが多く、最近Flutterを使っています。
基本的なところから、まとめていただいる、kazutxtさんのFlutter実践入門、大変わかりやすく参考させていただきました。
ありがとうございます。

一点、細かいですがソースとキャプチャーの相違を見つけましたので、お知らせします。
Chapter 12>01.画面の構築>Step1.文字を表示させる
この箇所、ソースと画面キャプチャーが違ってませんでしょうか。
ソースでは以下のようにHelloWorldになっていますが
~body: Text("HelloWorld"),
画面キャプチャーでは「初めてのテキスト」となっております。
ご確認いただけれと思います。

kazutxtkazutxt

ご連絡ありがとうございます。
また、日頃から本書をご利用いただきまして、本当にありがとうございます。

コメント頂きました箇所につきましては、ご指摘の通りソースコードとキャプチャが一致しておりませんでした。(キャプチャ側が誤り)
つきましては、先程修正を行い、該当ページを更新させていただきました。

IoTLikeIoTLike

いつも勉強になっております、執筆ありがとうございます。

大変恐縮ではございますが、Bluetoothを使用した内容について今後追加の予定はありますでしょうか?

kazutxtkazutxt

いつもご利用ありがとうございます。
申し訳ございませんが、現時点で執筆の計画はしておりません。

ただし、今回コメントを頂きまして、今後市場やニーズなども含めて調査を行い、重要度が高い場合には執筆を検討させて頂きたいと思います。

KazutoMakinoKazutoMakino

初学者ですが,自前スマホアプリ作成にあたり,当該書籍が大変役立っており感謝しています!

恐縮ではございますが,個人的に写経/実行していてエラーで躓いたところについて共有させていただきます.
必要に応じて,以下,加筆修正いただければ幸いです.

【バージョン情報】
Flutter 3.3.8 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 52b3dc25f6 (13 days ago) • 2022-11-09 12:09:26 +0800
Engine • revision 857bd6b74c
Tools • Dart 2.18.4 • DevTools 2.15.0

【該当ページ】
Chapter 34 06.MachineLearning https://zenn.dev/kazutxt/books/flutter_practice_introduction/viewer/34_chapter4_ml

【症状】
当該ページのコードや設定をコピペし,Android にて画像認識は問題なく実行できたのですが,OCR を実行しようしたところエラーで強制終了しました.

【自己解決した方法】
実装例の lib/main.dart について,

final textRecognizer = TextRecognizer(script: TextRecognitionScript.japanese);

とあり日本語を指定していますが,android/app/build.gradle (IOS は ios/Podfile) について,

android {
    ...略...
    dependencies {
        implementation 'com.google.mlkit:text-recognition-japanese:16.0.0-beta5'
    }
    ...略...
}

という風に dependencies を追加することで解決しました.
これの解決に当たり,公式ドキュメント https://pub.dev/packages/google_mlkit_text_recognition を参照いたしました.

kazutxtkazutxt

ご連絡ありがとうございます。
また、細かく丁寧な情報提供も大変ありがたく存じます。

まず、該当箇所は、執筆時のバージョンよりあとの最新版では明示的な依存関係への記述が必要になったようです。
対処方法は、ご記載頂いた内容と頂いた公式URLの通り、依存関係に言語ファイルに関する指定をするのが正しい対処で間違いないと思われます。

つづいて、本書ドキュメントの修正につきましては、バージョンアップの問題はどのライブラリでも常に発生しえる、かつ、全部を恒常的にメンテナンスすることは難しいため、次回の全体のバージョンアップを行う改定時に、動作検証やスクリーンショット等の取り直しも含めて実施させて頂ければと思います。

代わりに、本件のようなバージョンアップ時に最新情報への追従が必要なケースに対して注意を促すために、Chapter0の注意事項に最新バージョンが記載のものと異なっている場合は、依存関係が増えたり新しい設定が必要になる可能性がある旨を追記したいと思います。

KazutoMakinoKazutoMakino

ご返信/ご検討いただきありがとうございます.

該当箇所は、執筆時のバージョンよりあとの最新版では明示的な依存関係への記述が必要になったようです。
バージョンアップに伴う変更とのことで,仰る通り,毎回修正することは避けたいですね.

こちらの調査が足らず,面倒なことをお願いしてしまい失礼いたしました.

つづいて、本書ドキュメントの修正につきましては、バージョンアップの問題はどのライブラリでも常に発生しえる、かつ、全部を恒常的にメンテナンスすることは難しいため、次回の全体のバージョンアップを行う改定時に、動作検証やスクリーンショット等の取り直しも含めて実施させて頂ければと思います。

ご提案いただいた通り,全体をアップデートされる機会があれば,その時に盛り込んでいただければ幸いです.

yutakauyutakau

勉強させていただいています。ありがとうございます。
Youtube, Udemy, web検索などでFlutterのサンプルコードを探すのですが、
最新バージョンにちゃんと追従できているものは非常に少なく、この本は非常にありがたいです。

さて、気づいた点をご連絡します。

04.TTS(文字の音声化)
において、
lib/main.dart
の先頭でgeolocater をimport しています。
これは
import 'package:flutter_tts/flutter_tts.dart';
ですね。コピペの修正漏れかなと思いますが、上記修正で動作確認しました。
よろしくお願いします。

kazutxtkazutxt

ご連絡ありがとうございます。

該当箇所はご指摘の通り、geolocatorではなくflutter_ttsが正しい内容となっておりました。
geolocatorはGPSの項目で利用したライブラリですので、ご推察の通り他項目からのコピペミスだと思われます。

内容の修正に関しましては、2月中に大規模な最新版への追従更新を予定しておりますので、このタイミングで合わせて修正させて頂きます。
ご指摘ありがとうございました!

ykrodsykrods

Flutter 初学者ですが大変参考にさせていただきました。ありがとうございます。一点、違和感を感じたところを共有させていただきます。

【対象ページ】
Chapter 7, 04. Riverpod

【内容】
HookConsumerWidget で書き換えている部分について、「Consumer を使わずに buildメソッドでrefが使えるようにする」だけであれば hooks_riverpod は不要で、flutter_riverpod の ConsumerWidget で書き換えることができます。コメントの最後に書き換えたコードを貼っておきます。

hooks_riverpod の HookConsumerWidget は flutter_hook ( useState) と Riverpod ( ref ) を両方同じ Widget で利用したい場合に選択するものと解釈しており、(flutter_hook の) useState によってサンプルがより簡潔に書けるという解説は Riverpod の解説からはそれてしまっているように感じました。

import 'package:flutter/material.dart';
import 'package:riverpod/riverpod.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';


final _mydataProvider = StateNotifierProvider<MyData, double>((ref) => MyData());

void main() => runApp(ProviderScope(child: MyApp()));


class MyData extends StateNotifier<double> {
  MyData() : super(0.5);
  void changeState(state) => this.state = state;
}


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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: const MyHomePage(title: "Riverpod Demo"),
      theme: ThemeData(primarySwatch: Colors.blue),
    );
  }
}


class MyHomePage extends ConsumerWidget {
  final String title;

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

  
  Widget build(BuildContext context, WidgetRef ref) {
    double slidevalue = ref.watch(_mydataProvider);

    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            slidevalue.toStringAsFixed(2),
            style: const TextStyle(fontSize: 100),
          ),
          Slider(
            value: slidevalue,
            onChanged: (value) {
              ref.read(_mydataProvider.notifier).changeState(value);
          }),
        ],
      ),
    );
  }
}

kazutxtkazutxt

コメント頂きまして、ありがとうございます。
サンプルソースコードも大変参考になります。

該当箇所はご指摘の通り、(動作上の間違いではないものの)わざわざHookConsumerWidgetを使う必要はなく、この時点においては、「buildメソッドでrefが使えるようにする」事ができれば目的が達成できますので、flutter_riverpodのConsumerWidgetだけで十分であることは確認できました。

現在のHookConsumerWidgetをConsumerWidgetに置き換えて、Hooksのパッケージのインストールの前に持っていくか、あるいは、ConsumerWidgetでもできる旨を追記するかなどの修正方法は別途検討させて頂ければと思います。

貴重なご意見ありがとうございました。