0%

Flutter Web Migration - 使用conditional import處理跨平台功能

上一篇有提到真的有重要的功能不支援web的情況下,可以採用conditional import的方式,在不同平台運行不同的程式片段,避免使用過多的平台判斷邏輯造成程式碼過長,或是在compile階段出現error。

假設今天要實作一個platform判斷邏輯,因為我們已經知道web平台不支援dart:io,且其他的平台(ios, android等)都可以用dart:io.Platform。所以設計的邏輯為,當dart:io能被使用時採用dart:io.Platform判斷運行平台,否則即判定為web。

首先可以先作一個簡單的列舉項目PlatformType,用來比較platform判斷結果。接著設計一個PlatformCheck類別,並實作類似dart:io的isPlatform檢查。而checkPlatform函式會實作在拆出去的platform_web或platform_io兩個dart裡面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// platform_type.dart
import 'platform_web.dart' if (dart.library.io) 'platform_io.dart';

enum PlatformType {
WEB,
ANDROID,
IOS
}
class PlatformCheck {
static bool isWeb() => checkPlatform() == PlatformType.WEB;
static bool isAndroid() => checkPlatform() == PlatformType.ANDROID;
static bool isIos() => checkPlatform() == PlatformType.IOS;
// ...other platform
}

回頭看開頭的conditional import,我們想到達成的效果為,如果可以使用dart.library.io的話就import platform_io.dart,不行的話則import platform_web.dart。

所以只要分別在platform_io.dart實作非web平台的checkPlatform函式,接著在platform_web.dart實作web平台的checkPlatform函式即可。
如果今天app是運行在可以使用dart:io的非web平台上,platform_io.dart就會被import進來,接著就可以在checkPlatform裡面實作使用dart:io.Platform的平台判斷邏輯。

1
2
3
4
5
6
7
8
9
10
// platform_io.dart
import 'dart:io' show Platform;
import 'package:webapp/platform_type.dart';

PlatformType checkPlatform() {
if (Platform.isIOS) return PlatformType.IOS;
if (Platform.isAndroid) return PlatformType.ANDROID;

return PlatformType.IOS;
}

如果app是運行在不能使用dart:io的web平台上,會變成import platform_web.dart,因為目前只有web平台無法使用dart:io,所以如果是web情況下checkPlatform就不作其他的邏輯判斷,直接回傳是web。

到這裡可以再往回看一次,如果是運行在web平台上,在程式compile時就完全不會import到platform_io.dart,可以避免在web平台上import dart:io造成的compile錯誤。

1
2
3
4
5
6
// platform_web.dart
import 'package:webapp/platform_type.dart';

PlatformType checkPlatform() {
return PlatformType.WEB;
}

最後只要import自己寫的platform_type.dart,就可以用以下的語法達成跨平台的platform檢查。如果今天app是運行在web之下,就會回傳web。

1
2
3
4
5
6
String currPlatform = "";
if (PlatformCheck.isWeb()) currPlatform = 'Web';
else if (PlatformCheck.isAndroid()) currPlatform = 'Android';
else if (PlatformCheck.isIos()) currPlatform = 'iOS';

>>> WEB

如果專案在考量到web平台下,勢必會遇一個功能在不同的平台上要運行不同的package或是程式片段的跨平台問題。比起使用多個if-else的platform判斷邏輯,再把所有程式碼都寫進每個if-else中,使用conditaional import的方式可以有效的規劃程式碼,也可以避免import到平台不支援的package造成的compile錯誤。

參考資料:
Conditional imports across Flutter and Web