Life is Really Short, Have Your Life!!

ござ先輩の主に技術的なメモ

FlutterでTextFieldに非同期で取得した結果を初期値に入れたい

色々探してやっとわかった..

flutter.institute

initStateに直接awaitって書くことは出来ない。そりゃそうだな。ビルドが終わってから状態を変え、再ビルドするという方法を探していた。

class MyWidget extends StatefulWidget {
    @override
    State createState() => new MyWidgetState();
}

class MyWidgetState extends State<MyWidget> {
    var _result;

    @override
    void initState() {
        loadAsyncData().then((result) {
            setState(() {
                _result = result;
            });
        });
    }
    
    @override
    Widget build(BuildContext context) {
        if (_result == null) {
            return new Container();
        }    
       return new TextField(initialValue :result);
    }
}

要約するとこうなる。

  • initStateの中にsetStateを用意して、非同期の結果をメンバ変数にいれる
  • setStateもいつ呼ばれるかわからんが、呼ばれるとbuildがもっかい走るので、resultの状態に応じてビルドするWidgetを変える。

うーん、今回はStateFulWidgetにしたけど、ProviderとStatelessWidgetでも同じことができる気がする... あとでやってみよう。

PrismのDialogServiceでDIしたViewModelが毎回初期化される

PrismのDialogServiceでDIしたViewModelに限って、毎回ViewModelのコンストラクタが呼ばれるという現象がありました。

prism:ViewModelLocator.AutoWireViewModel="True"にしているのにね。この設定にした場合、ViewModelのインスタンスはSingletonになってくれるが、DialogServiceで呼び出す小画面に限りなぜか・・・

  • バージョン: Prism.Wpf 7.2.0.1422

結論から言えば、このコードを書けばSingletonになってくれた。

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
      containerRegistry.RegisterSingleton<OrdeSearchPageViewModel>();
}

RegisterSingleton で、型に対象のVMのクラスを指定するだけだった。Prismの沼かもしれん。

Flutterでカメラで画像を撮って保存したい

まー、ありますわね。そーゆーのがね。

要件としては、写真撮ってメモを追加して何件かリストにしてPOSTだから、取った写真をリスト表示できることが必要。これが意外と難しくてワロタ。

最終的に、こういう風にするしかなさげ。

  • image_pickerプラグインで画像をカメラでとって、
  • path_providerにて、application内のディレクトリに保存してパスを持っておく
  • ギャラリーに移す場合は、gallary_saverでファイルをコピーする。
  • image_gallay_saverはバグがあって動かないようだ。

まとめ

ギャラリーに直接保存してしまうと、保存先のファイルパスが取れない。戻り値がboolになるのは、gallary_saverの仕様。

  Future<bool> takePhoto() async {
    final ImagePicker picker = ImagePicker();
    final PickedFile _image = await picker.getImage(source: ImageSource.camera);
    return GallerySaver.saveImage(_image.path)
  }

true/falseより、保存先のパスが一番欲しいよねw issueに上がってるけど、できないのかな。FlutterのMethodChannel#invokeMethod型のFuture返すから、頑張れば取れる可能性も微レ存。flutterの仕様的に。

github.com

あ、あとこのライブラリでやると、画像がギャラリーに保存できなかった。issueも上がってる。

pub.dev

こんだけのコードなんだけどね。多分MethodChannelの使い方が間違っているのだろう。

import 'dart:async';
import 'dart:typed_data';

import 'package:flutter/services.dart';

class ImageGallerySaver {
  static const MethodChannel _channel =
      const MethodChannel('image_gallery_saver');

  /// save image to Gallery
  /// imageBytes can't null
  static Future saveImage(Uint8List imageBytes, {int quality = 80, String name}) async {
    assert(imageBytes != null);
    final result =
    await _channel.invokeMethod('saveImageToGallery', <String, dynamic> {
      'imageBytes': imageBytes,
      'quality': quality,
      'name': name
    });
    return result;
  }

  /// Save the PNG,JPG,JPEG image or video located at [file] to the local device media gallery.
  static Future saveFile(String file) async {
    assert(file != null);
    final result =
    await _channel.invokeMethod('saveFileToGallery', file);
    return result;
  }

}

image_gallery_saver/image_gallery_saver.dart at master · hui-z/image_gallery_saver · GitHub

そんなかんじ。

Flutterのjson_serializableで無限ループになったら

おきまりの flutter pub run build_runner build を叩くと、エンドレスにビルドが走って終わらなくなった・・・。@JsonSerializable アノテーション以外のファイルまで見に行ってる。widget_test.dart を見に行くアホがおるかい。

英語でググってみたところ、このissueがあった。

github.com

どうやら、analyzer というFlutter内部で利用されるライブラリのバグのようで、0.39.170.39.14 にダウングレードしたら、ビルドできました...

ダウングレードするには、pubspec.yamlにこの記述を加筆するだけ。

dependency_overrides:
  analyzer: '0.39.14'

追記 2020.9.17

analyzer 0.40.2 で修正されたようです。めでたしめでたし。

Vue.jsでは親子関係の画面をネストされたルーティングで対応する

router.vuejs.org

例えば、お申し込みフォームが複数の画面に分かれているが、「1つの画面操作」として捉えて、データを管理したい場合等。

const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User,
      children: [
        {
          // /user/:id/profile がマッチした時に
          // UserProfile は User の <router-view> 内部で描画されます
          path: 'profile',
          component: UserProfile
        },
        {
          // /user/:id/posts がマッチした時に
          // UserPosts は User の <router-view> 内部で描画されます
          path: 'posts',
          component: UserPosts
        }
      ]
    }
  ]
})

chilren属性を使うだけ。便利。

TypeScriptのUNION型、これ便利なのか・・・

let a: string | number;

a = 'Hello';  // OK
a = 123;      // OK
a = true;     // NG

//取る時はこう
if(typeof a === "string") {
}
else if(typeof a === 'number') {
}

typeofで型を指定すれば、型推論により、自分の欲しい型でゲットできる。UNION型は便利だと結構もてはやされているけど、戻り値がUNIONだった時が非常に面倒...

ExpressというNode.jsのWAFがあるけど、request.query.hoge ってやった時に、hogeがstring/string[]/undefinedの可能性があるよね〜あるよね〜みたいな話になってだるすぎる。配列で返ってくる前提ならflaskみたいにrequest.getlistっていう関数にしてほしい。

ENUMのイケてるやつ、引数の型指定として使うのはわかるど、関数の戻り値でこっちが空気読んで戻り値の型を指定して取る行為に時間を取られるの、僕は嫌い。

Vue.js + TypeScript、なかなかおもしろいです

7月からそういうお仕事をやっている。

色んなUIを作るライブラリが豊富で、コンポーネントをたくさん作っておけば、色んな案件に流用できるだろうなぁ。クールなUIが爆速で作れる時代になってきた。ありがてぇ。UI開発が一番面倒だからなあ。

kintoneでもvueをサポートする手順が公開されているし、今年はVue.jsをちゃんと使えるようになるお

developer.cybozu.io