Dart/Flutter連載 の3本目です。
FlutterのWindows対応が正式版になったので軽く試してみました。
インストール
Flutterのいつものインストール手順でインストールします。
手順としては次の通り
- Flutterのサイトからstableのzipをダウンロード
- 適当なフォルダーに展開してflutter/binフォルダにパスを通す(今回は
%USERPROFILE%/flutter/bin
でアクセスするようにしました) flutter upgrade
で最新版にしてから、あとはflutter doctor
でどんどん足りないコンポーネントを入れていく
他の環境と違うのは、Visual Studio(Codeじゃない方)が必要なことですね。インストーラを起動したらC++を使ったデスクトップ開発を選択してインストールします。
今回の検証ではなくてもよいのですが、IDEとしてはAndroid Studioが便利なのでそれも入れました。FlutterとDartのプラグインも入れます。全部緑色になると気持ち良いですね。
Windowsデスクトップの有効化
CLI上でflutterコマンドを使って有効化します。
$ flutter config --enable-windows-desktop |
既存のプロジェクトでは次のコマンドでWindowsデスクトップのターゲットを追加できます。
> flutter create --platforms=windows . |
プロジェクトの作成とビルド
Android Studioでプロジェクトを作ります。New Flutter Pojectでプロジェクトを作成します。僕はターゲットの追加でLinuxとかmacOSも試しに追加してみたのでいろいろプラットフォームが多いですが、いくらつけてもAndroid Studio上で選択できるわけではありません。クロスコンパイルとかできると便利なんですけどね。
プロジェクトができたら、上段からWindows (Desktop)
を選んで実行すればWindowsのアプリがビルドされます。
サンプルにテキストフィールドだけ追加してみた感じのものがこちらです。何事もなく普通ですね。IMEも普通に使える。flutter build windows
でプロダクションビルドをしてみました。
Qt(Widgets)だとランタイム入れて50MBぐらいになったと思うのですが、build/Release/runner
だと21MBですね。フォントが1.5MB、アイコンが280KB、ランタイムが14MB、app.soというDartコードをビルドして作られたモジュールらしきものが4MB。ランチャーが75KB。zip圧縮すると8MBぐらいなので配布も楽勝ですね。Electronだと展開後は数100MB、圧縮しても1環境ごとに50MB(macOSのユニバーサルバイナリとかWindowsの32/64ビット両対応をやると2倍)なので1/10ぐらい。
$ du -h |
リソース使用量はかなり少ないですね。GPUはモバイルのRyzen 4900HSの内蔵GPUなのでそこまで強いわけじゃないですが、負荷はかなり小さいです。メモリ使用量もQt並み。そのうちソフトウェアの二酸化炭素排出量が・・・みたいな話になったらFlutterは良さそう。
ついでにLinuxのコードも見てみる
安定版になったのはWindowsだけですが、Linuxも興味本位で覗いてみました。ビルド設定ファイルを見ると、GTKを使っていているようですね。GLFWでOpenGLベースのものも選べると。GTKなのでUbuntuとかのLinuxデスクトップであればIME対応も問題なさそうです。
https://github.com/flutter/engine
group("linux") { |
ライブラリ対応
なお、Flutterのライブラリはマルチプラットフォーム対応はパッケージごとにだいぶ差がありますし、Windowsデスクトップ対応はその中でもかなり少ないです。例えば、人気のWebViewのパッケージのwebview_flutterとかflutter_inappwebviewは非対応ですが、flutter.dev公式のwebview_flutter_platform_interfaceなんかもでてきていて、ちょっとずつ使えるライブラリなんかも増えていくんじゃないかなと思います。
他のフレームワークとの比較
QtとかElectronだと、ウィンドウとは独立して「アプリケーション」やら「メインプロセス」といったものがあり、ウィンドウはその付属物という世界観となっています。DelphiとかWin32の直利用とかもみんなそうですね。なので1つのアプリケーションで多数のウィンドウを持つMDIみたいなのもあったりはしますが、Flutterは元々がモバイルの世界観なのか、アプリケーション==ウィンドウというところはちょっと違うなという感じがありますが、それはまあそういうもんだな、という感じで受け入れられそうな気はします。
Visual Studioだけじゃなくて、QtみたいにWindows SDKも使えたり、クロスプラットフォームビルドもできたりするといいのになぁ、と思ったりはしますが、なにより、使いやすい言語で開発できて、クロスプラットフォームでAndroidやiOSにも展開できて、というのは魅力的です。類似のソリューションもいくつかありますが、バイナリも小さくメモリ使用量も少ないところがよさそうですね。Tauriも面白そうですけどね。
ウェブサービスを開発しつつ、コンパニオンアプリをモバイルのついでにデスクトップ版も作るよ、というケースや、長時間動かしたあとの安定性とかはわかりませんがキオスク端末とかのWindows IoTみたいな長く使うOS環境で少ないメモリで動かすには良いかもしれません。
タスクトレイ常駐型アプリを作ってみる
ほとんどのシステムがウェブブラウザをインタフェースとして利用するウェブアプリケーションという時代にあって、ローカルでアプリケーションをわざわざ作る理由というのは、単体アプリケーションとして使えるほうが便利というもの以外に、システムに統合される便利UIを追加で提供する、みたいな理由があります。例えば、Google Driveはデスクトップ版のツールを入れたりするとローカルとの同期を取ったりできますし、AdobeやJetBrainsはアプリケーションの更新をダウンロードするインタフェースとして常駐プログラムを提供していたりします。
Flutterは使用するリソースがマルチプラットフォームな環境の割には少なそうなので、この手の常駐アプリにはよさそうです。常駐アプリでリソースを食いまくるのはみんな嫌がりますしね。
まず、Flutterはアプリ=ウィンドウ=アクティブなので、ウィンドウ非表示のままアプリを実行し続けるということがデフォルトではできません。そこは、パッケージのbitsdojo_windowの力を借りる必要があります。また、システムトレイはsystem_trayを利用しました。こちらはシステムトレイにアイコンを表示しつつ、コンテキストメニューを表示したり、アイコンを動的に切り替えたりといったことができます。
今回はWindowsに特化して説明しますが、各ライブラリはmacOSやLinuxにも対応しています。そちらは紹介しませんので興味のある方はそれぞれのライブラリのドキュメントを参照してください。
まずライブラリを追加します。
dependencies: |
まずは、bitsdojo_window側からやっていきます。WindowsであればWindows用のmain.cppの先頭に次の2行を足します。これでデフォルトでウィンドウが非表示になります。サンプルだとCUSTOM_FRAMEだかもつけていますが、これをするとウィンドウタイトルが消えて終了が面倒なので消しました。
|
ウィンドウが表示される際のサイズなどを設定します。サンプルだと最後にappWindow.show()をしていますが、常駐なのでそこの行は消しました。
import 'package:bitsdojo_window/bitsdojo_window.dart'; |
この後はappWindow経由でウィンドウを消したり表示したりができます。
次にsystem_tray周りのコードを追加します。まずはimportを足します。
import 'package:system_tray/system_tray.dart'; |
ウィンドウのステートのクラス、あるいはstatelessであればそのウィジェットそのものに以下のコードを足します。ここではコンテキストメニューは消していますが、サンプルにはコンテキストメニューの使い方もあります。ここはクリックされたらウィンドウを表示しているだけですが、本来ならメインウィンドウの閉じるが押されたらhide()する、表示時にアイコンをクリックしたらhide()するといったコードも必要でしょう(前者をどうやるかはまだ調べてません)。
extends State<MyHomePage> { _MyHomePageState |
アイコンはこちら↓のを使わせていただいております。Creative Commons By-SAです。いつも通り、pubspec.yamlにアセットとして追加します。
Professions and jobs icons created by Yogi Aprelliyanto - Flaticon
ビルドして動かしてみると、以下のようにアイコンがトレイに表示され、クリックしたら表示されることがわかります。
うまく用途にあうニーズが見つけられればFlutterでやろう! というのは説得できそうな感じがします。使えるチャンスをうかがっていきたいですね。