title: 翻桌吧!Flutter for Desktop
date: 2019-05-20
categories: Flutter
keywords:
自從 Google I/O 公開 Flutter for Web 之後大家便開始瘋狂測試,似乎都忘了它目前只是預覽版本,接下來大家另一個期待便是 Flutter 什麼時候開始支援桌面系統,今天剛好看到一篇令人心動的文章-Flutter for Desktop: Create and Run a Desktop Application,這篇文章使用的是 Google 之前在 GitHub 上釋出的試驗性專案 flutter-desktop-embedding,這也意味著目前官方的進度,接下來當然實機測試看看了。
首先我們先下載 flutter-desktop-embedding 專案,可以直接下載壓縮檔或是透過 Git 指令下載。git clone https://github.com/google/flutter-desktop-embedding.git
開啟專案內的 README.md
可以看到各個開發需要的安裝的工具。
You will need developer tools for your platform:
Linux: A recent version of GCC
macOS: The current version of Xcode
Windows: Visual Studio 2017 or 2019, including the “Desktop development with C++” workload.
因為筆者是在 Windows 上所以需要安裝 Visual Studio 2017 以上的版本,特別要注意的是需要安裝 **使用 C++ 的桌面開發(Desktop development with C++)**。
若未安裝 **使用 C++ 的桌面開發(Desktop development with C++)**,執行時會出現找不到 vcvars64.bat 的錯誤。
接下來我們開啟專案內的範例程式 flutter-desktop-embedding\example\
,從 pubspec.yaml
內可以看到執行環境需要 Flutter SDK 1.5.9-pre.270 以上版本。
如果沒有修改,在下載 packages 時也會提醒。
如果版本太低可透過指令 flutter upgrade
來升級 SDK 版本,透過 flutter --version
可以查看目前的版本資訊,筆者目前版本為 1.6.1-pre.41。
開啟範例程式的 README.md(flutter-desktop-embedding\example\README.md
) 可以知道還需要新增一個環境變數 ENABLE_FLUTTER_DESKTOP
,並將值設為 true
。
{% codeblock README.md lang:md %}
The desktop support in the flutter
tool is still highly experimental, and
must be enabled with an environment variable. Run the command below in the
terminal/console you will be using to build and run the example.
On macOS or Linux:
export ENABLE_FLUTTER_DESKTOP=true
On Windows:
PowerShell:
$env:ENABLE_FLUTTER_DESKTOP="true"
CMD:
set ENABLE_FLUTTER_DESKTOP=true
{% endcodeblock %}
透過指令 flutter devices
,可以驗證是否連結成功。
接下來透過開啟終端機並切換到範例程式的路徑 flutter-desktop-embedding\example
,最後透過指令 flutter run
來執行,效果如下:
開啟 main.dart
可以看到其實與原本我們自己建立的專案幾乎一樣,比較明顯的是在呼叫 runApp
之前特別將執行的環境設為 fuchsia
。
{% codeblock main.dart lang:dart %}
void main() {
// See https://github.com/flutter/flutter/wiki/Desktop-shells#target-platform-override
debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
runApp(new MyApp());
}
{% endcodeblock %}
這主要是因為目前 TargetPlatform 只有 android
、fuchsia
、iOS
3種,目前桌面系統均無法識別,為了避免發生錯誤,所以暫時設定為 fuchsia
,這樣也可避免將 Package 與 Android 或 iOS 相關的部分一起打包進來。
與之前測試 Flutter for Web 時一樣,我們套用上一篇文章 Flutter 當我們黏在一起:Provider 的範例。
我們用開發工具開啟範例專案,筆者是用 Visual Studio Code,並在 pubspec.yaml
內加入 provider
這個 package,儲存後透過 flutter package get
來下載(VS Code 儲存 pubspec.yaml
時會自動執行指令)。
接著將 rx.dart
複製到 lib
資料夾下。
最後將 main.dart
內 MaterialApp 的 home
改為 RxPage。
在透過指令 flutter run
重新執行,可以看到操作效果與 App 以及 Web 一樣。
完整程式碼如下:
{% codeblock main.dart lang:dart %}
import ‘dart:io’ show Platform;
import ‘package:flutter/foundation.dart’ show debugDefaultTargetPlatformOverride;
import ‘package:flutter/material.dart’;
import ‘package:provider/provider.dart’;
import ‘package:example_flutter/rx.dart’;
final controller = StreamController
void main() {
// See https://github.com/flutter/flutter/wiki/Desktop-shells#target-platform-override
debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia;
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: ‘Flutter Demo’,
theme: ThemeData(
primarySwatch: Colors.blue,
// See https://github.com/flutter/flutter/wiki/Desktop-shells#fonts
fontFamily: ‘Roboto’,
),
// home: MyHomePage(title: ‘Flutter Demo Home Page’),
home: StreamProvider.value(
initialData: false,
stream: controller.stream,
child: RxPage(),
),
);
}
}
class RxPage extends StatefulWidget {
@override
_RxPageState createState() => _RxPageState();
}
class _RxPageState extends State
@override
Widget build(BuildContext context) {
List
bool isLogin = Provider.of
if (isLogin) {
list.add(UserAccountsDrawerHeader(
accountEmail: Text(“jonnyhuang@outlooj.com“),
accountName: Text(“Jonny”),
currentAccountPicture: CircleAvatar(
child: Text(“J”),
),
));
} else {
list.add(DrawerHeader(
decoration: BoxDecoration(
color: Colors.orange,
),
child: Text(“Guest”),
));
}
list.add(ListTile(
title: Text(isLogin ? “登出” : “登入”),
trailing: Icon(Icons.exit_to_app),
onTap: () {
controller.add(!isLogin);
},
));
return Scaffold(
appBar: AppBar(
title: Text('RxDart'),
),
drawer: Drawer(
child: ListView(
children: list,
),
),
body: Page1Page(),
);
}
}
class Page1Page extends StatefulWidget {
@override
_Page1PageState createState() => _Page1PageState();
}
class _Page1PageState extends State
@override
Widget build(BuildContext context) {
bool isLogin = Provider.of
return Scaffold(
body: Container(
color: isLogin ? Colors.green : Colors.grey,
alignment: Alignment.center,
child: MaterialButton(
child: Text(isLogin ? “登出” : “登入”),
onPressed: () {
controller.add(!isLogin);
},
),
),
);
}
}
{% endcodeblock %}
比起 Flutter for Web 的進度似乎還有點落後,但是我們可以看到 Flutter 移植到其他平台時修改幅度並不大,可以看的出來 Flutter 團隊不只是想讓 Flutter 只是可以在各種平台上執行而已,減少重工降低維護成本在實務應用上更加重要,這不論是對於公司還是個人來說應該都是很大的導入誘因。