Flutter中的依赖注入——get_it

Flutter社区的一个library: get_it

视频介绍:Flutter Dependency Injection For Beginners | Complete Guide
视频对应的博文 :Dependency Injection in Flutter

官网的介绍:

Simple direct Service Locator that allows to decouple the interface from a concrete implementation and to access the concrete implementation from everywhere in your App

关于什么是Service Locator:

If you are not familiar with the concept of Service Locators, its a way to decouple the interface (abstract base class) from a concrete implementation and at the same time allows to access the concrete implementation from everywhere in your App over the interface. I can only highly recommend to read this classic article by from Martin Fowler Inversion of Control Containers and the Dependency Injection pattern

所以Service Locator可以将接口(抽象基类)与具体实现分离,同时允许通过接口从App中的任何位置访问具体实现。

对于依赖注入不是很了解的同学可以参考:


为什么要使用get_it

我们也可以通过其他的方式在app中的任意位置获取到要访问的对象,但是:

  • 如果使用Singleton,则无法轻松地将实现切换到另一个(例如用于单元测试的模拟版本)
  • 用于依赖项注入的IoC容器提供了类似的功能,但代价是启动时间慢且可读性差,因为您不知道神奇注入的对象来自何处。 由于大多数IoC库都依赖反射,因此它们不能与Flutter一起使用。

使用场景

  • 访问诸如REST API客户端,数据库之类的服务对象,以便可以轻松模拟它们
  • 从Flutter视图访问View / AppModels / Manager
  • 由于接口和实现是分离的,因此您还可以在不同的实现中注册Flutter Views,并在启动时确定要使用的视图,例如 取决于屏幕分辨率

使用注意事项

按照官方解释:始终使用相同的样式将项目文件作为相对路径或我建议的包导入。 不要混用它们,因为虽然两种导入方式都引用相同的文件,但目前Dart将以不同方式导入的类型视为两种不同的类型。

比如我们在lib根目录下新建了一个Service Locator,我们要在不同的文件中使用,可以使用以下两种方式导入,官方的意思是应该一直使用同一种方式导入。

那么如果真的混合使用,会有什么影响吗?我试过在不同的文件中使用不同的导入方式混用,但没发现异常,且locator对象本来就是一个单例的,
知道的人可以告诉一下我,?

import '../../locator.dart';
import 'package:provider_architecture/locator.dart';

如何使用

  1. 获取GetIt对象
GetIt getIt = GetIt.instance;

//There is also a shortcut (if you don't like it just ignore it):
GetIt getIt = GetIt.I;
  1. 注册
sl.registerSingleton<AppModel>(AppModelImplementation());
sl.registerLazySingleton<RESTAPI>(() =>RestAPIImplementation());

// if you want to work just with the singleton:
GetIt.instance.registerSingleton<AppModel>(AppModelImplementation());
GetIt.I.registerLazySingleton<RESTAPI>(() =>RestAPIImplementation());
  1. 获取服务对象
var myAppModel = sl.get<AppModel>();
var myAppModel = sl<AppModel>();

// as Singleton:
var myAppModel = GetIt.instance<AppModel>();
var myAppModel = GetIt.I<AppModel>();
  1. 注册的种类
  • Factory工厂模式
void registerFactory<T>(FactoryFunc<T> func)
  
  locator.registerLazySingleton(() => Api());
  locator.registerFactory(() => HomeModel());

传入参数是一个函数func,这个func函数要返回一个实现了类型T的对象,每次调用获取对象的方式时,都会返回一个新对象

  • 单例模式&懒加载单例

单例注册时,传入一个范型T的对象或其子类的对象,如果创建这个单例时是耗时的,那么可以不在app启动的时候注册,而放到第一次使用到该服务的时候,即使用懒加载的方式。

void registerSingleton<T>(T instance) 

void registerLazySingleton<T>(FactoryFunc<T> func)

一个例子:

在app启动的时候调用注册方法

void main() {
  setupLocator();
  runApp(MyApp());
}

注册方法内部细节

单独的locator.dart文件:

GetIt locator = GetIt.instance;

void setupLocator() {
  locator.registerLazySingleton(() => Api());
}

在数据类中使用服务


  Api _api = locator<Api>();

  List<Comment> comments;

  Future fetchComments(int postId) async {
    ...
    comments = await _api.getCommentsForPost(postId);
    ...
  }
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页