Kimama-IT

ITに関する覚書き

【Flutter/Dart】CORSポリシーエラーによりImage.network()で画像が取得できないときの対処法

Web(Chrome)使用時に、CORSポリシーエラーによりImage.network()が画像を取得できないときの対処メモです。

参照したページ
docs.flutter.dev
docs.flutter.dev

対処法1:コンソールからrunコマンドを使用してHTMLレンダーで実行する。

flutter run -d chrome --web-renderer html

対処法2:webフォルダの中のindex.htmlの内容を書き換えてHTMLレンダーで実行する。

web -> index.htmlのbody要素を以下に書き換える。
let useHtml= true; でHTMLレンダーで実行
let useHtml= false; でCanvasKitレンダーで実行

<body>
  <script>
    let useHtml = true;

    window.addEventListener('load', function(ev) {
    _flutter.loader.loadEntrypoint({
      serviceWorker: {
        serviceWorkerVersion: serviceWorkerVersion,
      },
      onEntrypointLoaded: function(engineInitializer) {
        let config = {
          renderer: useHtml ? "html" : "canvaskit",
        };
        engineInitializer.initializeEngine(config).then(function(appRunner) {
          appRunner.runApp();
        });
      }
    });
  });
  </script>
</body>

lib -> main.dart

import 'package:flutter/material.dart';

void main() {
  // Web(chrome)でこのまま実行すると、CORSでエラーとなり画像が表示されない。
  // 以下のコマンドで実行して、htmlレンダーに変更することでエラーを回避する。
  // flutter run -d chrome --web-renderer html
  // または、webフォルダの中のindex.htmlの内容を書き換えることでhtmlレンダーに変更することができる。
  final imgNet1 = Image.network(
    'https://placehold.jp/150x150.png',
  );

  final imgNet2 = Image.network(
    'https://placehold.jp/3d4070/ffffff/150x150.png',
  );

  final imgNet3 = Image.network(
    'https://picsum.photos/250?image=9',
  );

  final col = Column(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [imgNet1, imgNet2, imgNet3],
  );

  final a = MaterialApp(
    home: Scaffold(
      body: Center(
        child: col,
      ),
    ),
  );
  runApp(a);
}

【Flutter/Dart】画像の使用例

Image.asset()・Image.network()を使用した時のメモです。

参照ページ
github.com

import 'package:flutter/material.dart';

// Imageの種類
// Image.asset()
// Image.network()
// Image.memory()
// Image.file()

void main() {
  // 画像
  final imgAss = Image.asset(
    'images/sushi.jpeg',
  );

  final imgNet1 = Image.network(
    'https://picsum.photos/250?image=9',
  );

  final imgNet2 = Image.network(
    'https://docs.flutter.dev/assets/images/dash/dash-fainting.gif',
  );

  // カラム
  final col = Column(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [imgAss, imgNet1, imgNet2],
  );

  // ロー
  final row = Row(
    mainAxisAlignment: MainAxisAlignment.spaceAround,
    crossAxisAlignment: CrossAxisAlignment.center,
    children: [col, col, col],
  );

  // アプリ
  final a = MaterialApp(
    home: Scaffold(
      body: Center(
        child: row,
      ),
    ),
  );
  runApp(a);
}

【Flutter/Dart】表示位置について

MainAxisAlignment・CrossAxisAlignment・MainAxisSizeをいろいろ変えたときの表示の違いを確認した時のメモです。

参照したページ
github.com

import 'package:flutter/material.dart';

void main() {
  // カラム
  const col1 = Column(
    // mainAxisAlignment: MainAxisAlignment.center,
    // crossAxisAlignment: CrossAxisAlignment.start,
    mainAxisSize: MainAxisSize.min,
    children: [
      Text('レモン'),
      Text('グレープフルーツ'),
      Text('ブドウ'),
    ],
  );

  const col2 = Column(
    // mainAxisAlignment: MainAxisAlignment.center,
    crossAxisAlignment: CrossAxisAlignment.end,
    // mainAxisSize: MainAxisSize.min,
    children: [
      Text('マンゴー'),
      Text('ナシ'),
    ],
  );

  // ロー
  const row = Row(
    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
    crossAxisAlignment: CrossAxisAlignment.end,
    children: [col1, col2, col1],
  );

  // アプリ
  const app = MaterialApp(
    home: Scaffold(
      body: Center(
        child: row,
      ),
    ),
  );

  runApp(app);
}

【Flutter/Dart】変数の型について

各変数の型が何になるか確認した時のメモです。

void main() {
  print('---var---');
  var nameVar = 'Bob';
  print(nameVar.runtimeType);
  print(nameVar);
  print('');
  print('---Object---');
  Object nameObj = 'Bob';
  print(nameObj.runtimeType);
  print(nameObj);
  print('');
  print('---String---');
  String nameStr = 'Bob';
  print(nameStr.runtimeType);
  print(nameStr);
  print('');
  print('---Map---');
  Map mapDyn = {
    1: 0,
    2: 1,
    '3': '2',
  };
  print(mapDyn.runtimeType);
  print(mapDyn[2]);
  print('');
  print('--- Map<String, int>---');
  Map<String, int> mapSta = {
    '1': 0,
    '2': 1,
    '3': 2,
  };
  print(mapSta.runtimeType);
  print(mapSta['2']);
  print('');
  print('---enum PlanetType.values---');
  print(PlanetType.values.runtimeType);
  print(PlanetType.values);
  print('');
  print('---enum PlanetType.terrestrial---');
  print(PlanetType.terrestrial.runtimeType);
  print(PlanetType.terrestrial);
  print(PlanetType.terrestrial.name);
  print(PlanetType.terrestrial.index);
  print('');
  print('---enum PlanetType.values[0]---');
  print(PlanetType.values[0].runtimeType);
  print(PlanetType.values[0]);
  print(PlanetType.values[0].name);
  print(PlanetType.values[0].index);
  print('');
  print('---enum Planet.values---');
  print(Planet.values.runtimeType);
  print(Planet.values);
  print('');
  print('---enum Planet.mercury---');
  print(Planet.mercury.runtimeType);
  print(Planet.mercury);
  print('');
  print('---enum Planet.mercury.planetType---');
  print(Planet.mercury.planetType.runtimeType);
  print(Planet.mercury.planetType);
}

enum PlanetType { terrestrial, gas, ice }

enum Planet {
  mercury(planetType: PlanetType.terrestrial, moons: 0, hasRings: false),
  venus(planetType: PlanetType.terrestrial, moons: 0, hasRings: false),
  // ···
  uranus(planetType: PlanetType.ice, moons: 27, hasRings: true),
  neptune(planetType: PlanetType.ice, moons: 14, hasRings: true);

  /// 定数生成コンストラクター
  const Planet(
      {required this.planetType, required this.moons, required this.hasRings});

  /// すべてのインスタンス変数はfinal変数です
  final PlanetType planetType;
  final int moons;
  final bool hasRings;

  /// 強化された列挙型はゲッターやその他のメソッドをサポートします
  bool get isGiant =>
      planetType == PlanetType.gas || planetType == PlanetType.ice;
}

【Flutter/Dart】exception・throw・try・catchの使用例

公式ページのイントロダクションをもとにした使用例のメモです。

dart.dev

void main() {
  int astronauts = -1;
  try {
    if (astronauts <= 0) {
      throw StateError('No astronauts.');
    }
    print('$astronauts astronauts');
  } catch (e) {
    print(e);
  }
}
import 'dart:io';

void main() {
  describeFlybyObjects(flybyObjects);
}

var flybyObjects = ['Jupiter', 'Saturn', 'Uranus', 'Neptune'];

Future<void> describeFlybyObjects(List<String> flybyObjects) async {
  try {
    for (final object in flybyObjects) {
      /// libフォルダの中にJupiter.txtを配置しておく。
      var description = await File('lib/$object.txt').readAsString();
      print(description);
    }
  } on IOException catch (e) {
    print('Could not describe object: $e');
  } finally {
    flybyObjects.clear();
  }
}

【Flutter/Dart】Future・async・awaitの使用例

公式ページのイントロダクションをもとにした使用例のメモです。

dart.dev

void main() {
  print('${DateTime.now()} すぐに表示');
  printWithDelay('1秒後に表示されるかな?');
  print('${DateTime.now()} すぐに表示?');
}

const oneSecond = Duration(seconds: 1);

Future<void> printWithDelay(String message) async {
  await Future.delayed(oneSecond);
  print('${DateTime.now()} $message');
}

/// 上と下のメソッドは同じ動作をする。

// Future<void> printWithDelay(String message) {
//   return Future.delayed(oneSecond).then((_) {
//     print('${DateTime.now()} $message');
//   });
// }

gitのプログラムをもとにした使用例のメモです。

github.com

void main() {
  xxx();
}

xxx() async {
  print('${formate(DateTime.now())}  xxx: 私は x です');
  print('${formate(DateTime.now())}  xxx: y を await します');
  await yyy();
  print('${formate(DateTime.now())}  xxx: y を await しました');
}

Future yyy() async {
  print('${formate(DateTime.now())}  yyy: 私は y です');
  print('${formate(DateTime.now())}  yyy: z を await します');
  await zzz();
  print('${formate(DateTime.now())}  yyy: z を await しました');
}

Future zzz() async {
  print('${formate(DateTime.now())}  zzz: 私は z です');
  print('${formate(DateTime.now())}  zzz: 通信中...しばらくお待ちください');
  await Future.delayed(const Duration(seconds: 1));
  print('${formate(DateTime.now())}  zzz: 1秒後です');
}

String formate(DateTime datetime) {
  return "${datetime.hour}:${datetime.minute}:${datetime.second}.${datetime.millisecond}";
}

Flutterの初期カウントアップのプログラムに適用したときのメモです。

以下のサイトを参考にさせていただきました。
qiita.com

import 'package:flutter/material.dart';
import 'dart:io';

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> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
      print('onPressed インクリメントしました。');
    });
  }

  void _setCounter(int num) {
    setState(() {
      _counter = num;
    });
  }

  @override
  void initState() {
    print("MyHomePage画面が表示されました。");
    Async().asynctest3AndSetCount(_setCounter);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

class Async {
  void asynctest1() {
    print("method begin");
    print(DateTime.now().toString());
    print("data1 start");
    print(syncFunc("data1", 3));
    print("data2 start");
    print(syncFunc("data2", 2));
    print("data3 start");
    print(syncFunc("data3", 1));
  }

  void asynctest2() {
    print("method begin");
    print(DateTime.now().toString());
    print("data1 start");
    print(asyncFunc("data1", 3));
    print("data2 start");
    print(asyncFunc("data2", 2));
    print("data3 start");
    print(asyncFunc("data3", 1));
  }

  void asynctest3() async {
    print("method begin");
    print(DateTime.now().toString());
    print("data1 start");
    Future<String> result1 = asyncFunc("data1", 3);
    result1.then((result) {
      print(result);
    });
    print("data2 start");
    Future<String> result2 = asyncFunc("data2", 2);
    result2.then((result) {
      print(result);
    });
    print("data3 start");
    Future<String> result3 = asyncFunc("data3", 1);
    result3.then((result) {
      print(result);
    });
  }

  void asynctest3AndSetCount(Function setCounter) async {
    print("method begin");
    print(DateTime.now().toString());
    print("data1 start");
    Future<String> result1 = asyncFunc("data1", 8);
    result1.then((result) {
      print(result);
      setCounter(1000);
      print('data1 _Counterを1000に設定しました。');
    });
    print("data2 start");
    Future<String> result2 = asyncFunc("data2", 5);
    result2.then((result) {
      print(result);
      setCounter(2000);
      print('data2 _Counterを2000に設定しました。');
    });
    print("data3 start");
    Future<String> result3 = asyncFunc("data3", 2);
    result3.then((result) {
      print(result);
      setCounter(3000);
      print('data3 _Counterを3000に設定しました。');
    });
  }

  void asynctest4() async {
    print("method begin");
    print(DateTime.now().toString());
    print("data1 start");
    print(await asyncFunc("data1", 3));
    print("data2 start");
    print(await asyncFunc("data2", 2));
    print("data3 start");
    print(await asyncFunc("data3", 1));
  }

  // timeの時間分スリープし、その後現在時間を返す関数
  String syncFunc(String name, int time) {
    sleep(Duration(seconds: time));
    return name + ":" + DateTime.now().toString();
  }

  // timeの時間分スリープし、その後現在時間を返す関数
  Future<String> asyncFunc(String name, int time) async {
    return Future.delayed(Duration(seconds: time), () {
      return name + ":" + DateTime.now().toString();
    });
  }
}

【Flutter/Dart】enumの使用例

公式ページのイントロダクションをもとにした使用例のメモです。

dart.dev

void main() {
  print('-----Planet.values-----');
  print(Planet.values);
  print('');
  print('-----Planet.uranus-----');
  print(Planet.uranus);
  print('');
  print('-----Planet.uranus.name-----');
  print(Planet.uranus.name);
  print('');
  print('-----Planet.uranus.planetType-----');
  print(Planet.uranus.planetType);
  print('');
  print('-----Planet.uranus.planetType.name-----');
  print(Planet.uranus.planetType.name);
  print('');
  print('-----Planet.uranus.moons-----');
  print(Planet.uranus.moons);
  print('');
  print('-----Planet.uranus.hasRings-----');
  print(Planet.uranus.hasRings);
  print('');
  print('-----Planet.uranus.isGiant-----');
  print(Planet.uranus.isGiant);
  print('');

  print('/////giant planet or not/////');
  if (Planet.uranus.isGiant) {
    print('${Planet.uranus.name} is a "giant planet".');
  }
  print('');

  final planets = Planet.values;
  for (var p in planets) {
    if (!p.isGiant) {
      print('${p.name} is not a "giant planet".');
    } else {
      print('${p.name} is a "giant planet".');
    }
  }
}

enum PlanetType { terrestrial, gas, ice }

/// 太陽系のさまざまな惑星を列挙する列挙型
/// およびそのプロパティの一部。
enum Planet {
  mercury(planetType: PlanetType.terrestrial, moons: 0, hasRings: false),
  venus(planetType: PlanetType.terrestrial, moons: 0, hasRings: false),
  // ···
  uranus(planetType: PlanetType.ice, moons: 27, hasRings: true),
  neptune(planetType: PlanetType.ice, moons: 14, hasRings: true);

  /// 定数生成コンストラクター
  const Planet(
      {required this.planetType, required this.moons, required this.hasRings});

  /// すべてのインスタンス変数はfinal変数です
  final PlanetType planetType;
  final int moons;
  final bool hasRings;

  /// 強化された列挙型はゲッターやその他のメソッドをサポートします
  bool get isGiant =>
      planetType == PlanetType.gas || planetType == PlanetType.ice;
}