gradle下载中,闲的慌记录下
Kodeinn
Kodein有在类型擦拭问题上,有两种Flavor可选。
一种是常规不做处理,
一种是能够在运行时保留类型参数的。
注:类型擦拭简单解释,泛型作为类型参数,在编译成字节码之后其类型是不保留的,它的作用仅限于在编译前提供检查。
如:
List<Sring> strsList=new ArrayList<>()
strList.add("love word"); //没问题,如何其要求
strList.add(new Date()); // 编译不通过
但是,在runtime时,或是在字节码中,并不存在List::class,而是存在List<*>::class.
其结果就是,若是通过手动修改字节码是可以将一个日期类型的对象放入到一个字符串集合当中。这当然是一个坑,好处是,类型擦拭后,效率得以提高,坏处是,在一些框架中,反射机制的存在,有可能会为其添加一个不是预期的类型,当时不会立马报错,而是在使用时才把问题暴露处理,错误没能第一处理,会传播扩张。
回到Kodein,直接代码例子。
val kodein = Kodein {
//通过提供一个`Random`类型的实例`SercureRandom`对象,这个provider每次需要这个该类型的实例时,都会创造一个新的。
bind<Random>() with provider { SercureRandom() }
//看看一个常见的单例的例子,嗯,单例...
bind<Database>() with singetonn { SqliteDatabase() }
//还有很多提供的类型,先混个眼熟,multion, instance, ect
}
当一个类型存在多实例,即单纯通过一个类型,不能找到唯一的实例时,通过通过添加tag
来进一个区分,比如:
bind<Database>( tag = "local" ) with singleton { SqliteDatabase() }
bind<Database>( tag = "remote") with singleton { DatabaseProxy() }
//定义一个模块
val repositoryModule = Kodein.Module {
bind<Database>( tag = "local" ) with singleton { SqliteDatabase() }
bind<Database>( tag = "remote") with singleton { DatabaseProxy() }
}
前面的步骤做的工作已经创建好了我们需要的依赖,可以把这些称之为容器
。
那么下一步就是要如何在需要服务
的地方获取容器中的对象。
将容器中的对象交给它需要的类,其方法有两种。
一种是依赖注入
,其需求方在创建时,就将其需要的依赖注入。不需要感知其供应方的存在。
//作为需求方,可以看到其对象的创建需要两个依赖。
class Presneter(val db:Database, val rnd:Random){}
//以下面的方法,就可以将依赖传入
val presenter = Kodein.newInstance( Presenter(instance(),instance()) )
//使用instance(),Kodein会传入相应的依赖
第一种方法简单暴力,直接获取其依赖,而且也不绑定如何框架,缺点就是不灵活。看第二种方法,可以看到区别。
一种是主动获取
,其需求方在需要时,自己负责获取所需依赖。需要持有容器Kodein
,但是支持很多特性。
class Presneter( kodein : Kodein){
//默认情况下,依赖是懒加载的。所以下面两个语句是等同的
private val db: Database by kodein.instacne()
private val db: Database by { kodein.instacne() }
}
当然,既然有懒加载,相反的就是直接提供,即在需求方创建时,就像需求方所需的依赖创建,而不是等到使用到该依赖时才创建。如下
//提供方定义这个对象是直接提供就ok了
bind() from sinleton {Rondom (6) }
据说需求方(这里即Presenter)继承KodeinAware可以解锁更过姿势… todo
Tuturial end …
gralde卡死了