給 Mobile 開發者的 Flutter 入門 - 如何使用 GetIt 和 Injectable 來做 DI
TLDR
這篇主要是介紹如何透過 GetIt 和 Injectable 兩個套件,來完成 Flutter Dependency Injection 依賴注入(簡稱 DI)的功能。 這邊不多說明 DI 的概念,如果有興趣可以參考之前寫的文章 Android 的依賴注入框架-Dagger2(一)。有稍微提到什麼是 DI。
在過往 Android 開發中,一開始早期使用 Dagger2,到後來的 Koin,以及最近的 Hilt,所以在這邊也會把做法以及相似的部分做一個比較,也能讓 Android 開發者更容易理解。
以下我們會用一個簡單的例子來說明如何使用 GetIt 和 Injectable 來完成 DI 的功能。
GetIt
首先可以到 GetIt 的網站 GetIt 去將 GetIt 套件安裝至專案中,這邊不做多餘的贅述。GetIt 是一個簡單的 Service Locator,可以用來管理依賴的實例,這邊先來看一下 GetIt 的基本用法。
1 | import 'package:get_it/get_it.dart'; |
這邊我們先註冊一個 CounterService
的實例,然後在 App
的 build
方法中,透過 getIt<CounterService>()
來取得 CounterService
的實例,這樣就完成了一個簡單的 DI。
在這個簡單的例子中,可以想像一下我們的 setup 是一個 DI Provider,在 App 初始化之前提供了許多我們需要的物件實例,然後在 App 初始化的時候,透過 getIt 來取得這些實例,讓我們的代碼可以更加地解除耦合,那 get_it 也提供了更多的功能,像是我們在範例中,使用 registerSingleton 來註冊一個 Singleton 的實例,但有時候我們不是一開始就需要這些物件實例,而是希望等到後續有相關的業務代碼呼叫到的時候再去實例化,這時候我們可以使用 registerLazySingleton 來註冊一個 Lazy Singleton 的實例。
但是你會發現,當我們如果有很多的依賴,這樣的寫法會讓我們的 setup 方法變得很大,所以這時候我們可以使用 Injectable 來幫助我們更好的管理我們的依賴。這邊也會將加入 Injectable 來改寫上面的例子,以及比較一下跟 Koin, Heilt 的差異。
Injectable
Injectable 是一個 透過 Annotation 來生成 GetIt 的 相關代碼,讓我們可以更好的管理我們的依賴,這邊先來看一下 Injectable 的基本用法。
首先可以到 Injectable 的網站 Injectable 去將 Injectable 套件安裝至專案中,這邊不做多餘的贅述。
首先我們建立一個 injection.dart
1 | import 'package:injectable/injectable.dart'; |
然後我們建立一個 service_module.dart
1 | import 'package:injectable/injectable.dart'; |
接下來其實只要執行一下 flutter pub run build_runner build
就可以生成相關的代碼,然後我們就可以在我們的 App 中使用了。
1 | void main() async { |
生成後的代碼我們可以發現,在 injection.config.dart 中,會生成一個 GetItInjectableX 的 Extension,這個 Extension 會幫助我們初始化我們的依賴。
1 | extension GetItInjectableX on _i1.GetIt { |
熟悉 koin 跟 Hilt 的朋友應該會發現,這邊的 @module
跟 @singleton
跟 koin
/ Hlit
的 provider module 實作非常類似。
koin
1 | val myModule = module { |
Hilt
1 |
|
由上面的案例可能不覺得 Injectable 帶來什麼好處,那我們接下來來看一下這個複雜一點的案例,如果我們只使用 GetIt,我有一個 ServiceA 以及 ServiceB,然後 ServiceB 依賴 ServiceA,這時候我們可以這樣寫。
1 |
|
如果今天有更多依賴,我們必須手動去維護這些關係在 getIt 的 setup 中,透過 Injectable,可以透過註解快速的生成這些依賴關係。
1 |
|
其他 Injectable 還有更多類似 Koin/Hlit 的功能,像是 Binding abstract class to implementation class、name、scope 等相關功能, 這邊就不多做贅述,有興趣的朋友可以參考 Injectable 的官方文件。
以上就是一些在 Flutter 中使用 GetIt 以及 Injectable 來完成 DI 的功能,這邊也有提到一些跟 Android 開發中的 DI 框架的比較,希望這篇文章對大家有所幫助。