史蒂夫科恩_科特琳·科恩范围

2023-10-26

史蒂夫科恩

学习Android开发 (Learning Android Development)

If you are familiar with Dagger 2, you probably know that Scope an important part of Dependency Injection. It enables us to determine if we are getting the same dependent object or a new one.

如果您熟悉Dagger 2,您可能知道Scope是依赖注入的重要组成部分。 它使我们能够确定要获取相同的从属对象还是新的对象。

What about Koin, the popular Kotlin way of getting your dependencies? The scope documentation for core and android Koin is a good start, but I spent some time digging out all the gist of it. Here I provide some illustration, and some gotcha to watch out.

Koin是如何获得依赖的流行Kotlin方法呢? 核心android Koin的范围文档是一个不错的开始,但是我花了一些时间来挖掘它的全部要旨。 在这里,我提供一些说明,以及一些需要注意的地方。

单人和工厂 (Single and Factory)

The simplest scope available in Koin is single and factory.

Koin中最简单的范围是singlefactory

val koinModule =module {single(qualifier = named("singleName")) { Dependency() }factory(qualifier = named("factoryName")) { Dependency() }
}

To illustrate this easily, I use the same Dependency object for both single and factory scope. The are illustrated below

为了方便地说明这一点,我对single作用域和factory作用域使用相同的Dependency对象。 如下图所示

Single — always provide the same copy of Dependency object for the requester

单个-始终为请求者提供相同的Dependency对象副本

Factory — always provide a new copy of Dependency object for the requester

工厂-始终为请求者提供Dependency对象的新副本

To get the dependency, (as I qualified it with proper names), it is as below

要获取dependency (我用专有名称限定它),如下所示

val alwaysSameDependency = get<Dependency>(
qualifier = named("singleName")).toString()val alwaysNewDependency = get<Dependency>(
qualifier = named("factoryName")).toString()

知道了! (Gotcha!)

The single might sounds like it’s a Singleton. It is not really one, unless it is generated on the root module.

single力量的声音就像是一个单例 。 除非它是在根模块上生成的,否则它不是真正的一个。

For the case of it is in a loaded module as loaded

如果是在已加载的模块中

loadKoinModules(koinModule)

upon the lifetime of the module is loaded, it will always generate the same copy. However if the module is unloaded as below

在加载模块的生命周期时,它将始终生成相同的副本。 但是,如果按以下方式卸载模块

unloadKoinModules(koinModule)

and then reloaded later, a new copy of the single dependency will be created instead.

然后再重新加载,将改为创建single依赖项的新副本。

合格范围 (Qualified Scope)

Both single and factory live throughout the lifetime of the koin module loaded. However if we want some dependencies that has a scope differ from the module lifetime, we could use Qualified Scope. There are 2 of them.

在装入koin模块的整个生命周期中, single人和factory都可以使用。 但是,如果我们希望某些依赖项的作用域与模块生存期不同,则可以使用合格作用域。 有两个。

字符串合格范围 (String Qualified Scope)

Instead of dependent on the Module solely, we could create a Scope independently from the Module Lifetime.

我们可以创建一个独立于模块生命周期的作用域,而不是仅依赖模块。

val koinModule =module {scope(named("AScopeName")) {scoped(qualifier = named("scopedName")) { Dependency() }factory(qualifier = named("factoryName")) { Dependency() }
}
}

As we could see above, we have a scope with the name of AScopeName. To create the scope within the koinModule, just need to do the following.

正如我们在上面看到的,我们有一个名称为AScopeNamescope 。 要在koinModule创建范围,只需执行以下操作。

val stringQualifiedScope = getKoin().createScope(
"ScopeNameID", named("AScopeName"))

The ScopeNameID is the ScopeID that one could use to identify the Scope from one to the other. It is used internally as the Key (ID) to look for this scope. It’s used is described later.

ScopeNameID是ScopeID 一个人可以用来识别一个范围到另一个范围。 它在内部用作查找此范围的键(ID)。 稍后将对其进行描述。

Here we have scoped and factory.

在这里,我们确定了scopedfactory

Scoped — always provide the same copy of Dependency object from the Scope for the requester

作用域-始终为请求者提供作用域中相同的Dependency对象副本

Factory — always provide a new copy of Dependency object from the Scope for the requester

Factory —始终从范围为请求者提供Dependency对象的新副本

To get the dependencies, is as below

要获取依赖关系,如下

val alwaysSameDependency = stringQualifiedScope.get<Dependency>(
qualifier = named("scopedName")).toString()val alwaysNewDependency = stringQualifiedScope.get<Dependency>(
qualifier = named("factoryName")).toString()

To close away the scope (to end it life), one just need to call close as below

要关闭示波器(以终止使用寿命),只需按以下方式调用close

stringQualifiedScope.close()

类型合格范围 (Type Qualified Scope)

Type qualified scope is same as String Qualifies Scope with the exception it is not tied to a String named made up scope, but a variable type.

类型限定范围与字符串限定范围相同,不同的是它不是绑定到由命名范围组成的字符串,而是变量类型。

In example below, we have a class type Container, where once we have the object, we could get scope from it.

在下面的示例中,我们有一个类类型Container ,在其中有了对象后,就可以从中获取作用域。

val koinModule =module {factory { Container() }       scope<Container> {scoped(qualifier = named("scopedName")) { Dependency() }factory(qualifier = named("factoryName")) { Dependency() }
}
}

Actually TypeQualifiedScope is a little misnomer. It is actually differs from Object to Object even if they are of the same type (i.e. two

实际上, TypeQualifiedScope有点用词不当。 实际上,即使对象的类型相同(即两个

So to create the scope, we first need to get the Container object first.

因此,要创建范围,我们首先需要首先获取Container对象。

val container: Container = get()
val typeQualifiedScope = container.scope

To get the dependencies, is the same as stringQualifiedScope above.

要获取依赖项,与上面的stringQualifiedScope相同。

val alwaysSameDependency = typeQualifiedScope.get<Dependency>(
qualifier = named("scopedName")).toString()val alwaysNewDependency = typeQualifiedScope.get<Dependency>(
qualifier = named("factoryName")).toString()

To close away the scope (to end it life), one just need to call close as below

要关闭示波器(以终止使用寿命),只需按以下方式调用close

typeQualifiedScope.close()

知道了! (Gotcha!)

  • When getting scope from object e.g. container.scope, it is actually container.getOrCreateScope(), so if one uses container.scope.close(), container.scope still works as it create a new one, making one confuse why after closing, it could still be used

    从对象(例如container. scope获取范围时container. scope container. scope ,它实际上是container. getOrCreateScope() container. getOrCreateScope() ,因此如果使用container. scope. close() container. scope. close() container. scope. close()container. scope container. scope仍然有效,因为它创建了一个新的container. scope ,这使为什么在关闭后仍可以使用它感到困惑

  • For StringQualifiedScope, only after the close() is called on the scope, can one recreate a scope with the same ScopeID i.e. ScopeNameID, else it will crash. This doesn’t applies to TypeQualifiedScope though, as every time we get the scope from the object, it will provide the same scope instead of crashing.

    对于StringQualifiedScope,只有后close()被调用的范围,可以重新创建一个具有相同ScopeID即范围ScopeNameID ,否则会崩溃。 但是,这不适用于TypeQualifiedScope ,因为每次我们从对象获取范围时,它将提供相同的范围而不是崩溃。

  • Can we have single in the scope? NO. Only scoped is allowed. single is error out during compile time. Essentially scoped and single is the same thing, but used in different place. I propose to them to use the same name as in

    我们可以在scope single吗? 没有。 只允许scopedsingle在编译时出错。 本质上, scopedsingle是一回事,但是用在不同的地方。 我建议他们使用与

其他特性 (Other Features)

Other than the normal scope, there are other feature provided which is handy for scope usage. They are as below

除正常范围外,还提供了其他一些方便使用范围的功能。 他们如下

链接范围 (Link scope)

In order to get some dependencies of another scope from one scope, we could link them together.

为了从一个作用域中获得另一个作用域的某些dependencies ,我们可以将它们链接在一起。

E.g. the below diagram showing we link scope_a with scope_b as well as scope_a link with scope_a (we could link just one of them, but I’m showing they could link bidirectionally just to demonstrate that’s possible)

例如,下面示出图我们链接scope_ascope_b以及scope_a与链路scope_a (我们可以只链接其中之一,但是我正在展示它们可以双向链接只是为了证明这是可能的)

scopeA.linkTo(scopeB)
scopeB.linkTo(scopeA)

With that, we could

这样,我们可以

val somethingInScopeB = scopeA.get<SomeDependencyInScopeB>()
val somethingInScopeA = scopeB.get<SomeDependencyInScopeA>()

传递参数 (Passing parameters)

There are cases where we want some of our dependencies getting some specific parameter e.g. from which Scope it should gets it’s dependencies, or the qualified name.

在某些情况下,我们希望某些依赖项获取某些特定参数,例如,应该从哪个Scope获取依赖项或限定名称。

From the diagram below, we could send the parameter A, B and C, which is then provided to the dependency generator function.

从下图中,我们可以发送参数A,B和C,然后将其提供给依赖项生成器函数。

Below is an example, we have an Environment which is dependent on Dependency. So we have to tell Environment which scope should it get its Dependency from.

下面是一个示例,我们有一个依赖于DependencyEnvironment 。 因此,我们必须告诉Environment应该从哪个范围获得Dependency

class Environment(val dependency: Dependency)val mainKoinModule =module {single(qualifier = named("single")) { Dependency() }factory(qualifier = named("factory")) { Dependency() }scope(named("AScopeName")) {scoped(qualifier = named("scopedName")) { Dependency() }factory(qualifier = named("factoryName")) { Dependency() }
}
scope<Container> {scoped(qualifier = named("scopedContainer")) { Dependency() }factory(qualifier = named("factoryContainer")) {Dependency()}
}
factory { (scopeId: ScopeID, name: String) ->
Environment(getScope(scopeId).get(qualifier = named(name)))
}
}

In order to do that, we could pass the parameter over, upon what we set above

为了做到这一点,我们可以在上面设置的值上传递参数

(scopeId: ScopeID, name: String)

So the way to get it is

所以得到它的方法是

val scopeID = someScope.id // ScopeID is actually a String
val qualifiedName = "someQualifierval environment = get<Environment>(
parameters = { parametersOf(scopeID, qualifierName) })

Android生命周期范围 (Android Lifecycle Scope)

This is specifically to Android. (Note, you’ll need to get the koin-android library instead of koin-core library).

这是专门针对Android的。 (请注意,您需要获取koin-android库而不是koin-core库)。

You could define your module using your Activity as the Type.

您可以使用“活动”作为“类型”来定义模块。

val androidModule = module {
scope<MyActivity> {
scoped { Dependency() }
}
}

To get your dependencies, you’ll just need to use the lifecycleScope instead of normal scope as shown above.

为了获得依赖关系,您只需要使用lifecycleScope而不是上面显示的常规范围即可。

class MyActivity : AppCompatActivity() {
// inject Dependency instance from current scope
val dependency : Dependency by lifecycleScope.inject()

What does this provides further?

这进一步提供了什么?

Tracing down the code, it’s actually automatically close upon ON_DESTROY, hence you don’t need to close it. That’s it.

跟踪代码,实际上它会在ON_DESTROY时自动关闭,因此您无需关闭它。 而已。

@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)    
fun onDestroy() {
if (event == Lifecycle.Event.ON_DESTROY) {
scope._koin._logger.debug("$target received ON_DESTROY")
scope.close()
}
}
}

I have coded the example below. Check out if you have trouble working on them

我已将以下示例编码。 检查您在处理它们时是否遇到麻烦

Thanks for reading. You can check out my other topics here.

谢谢阅读。 您可以在此处查看我的其他主题。

Follow me on medium, Twitter, Facebook or Reddit for little tips and learning on mobile development etc related topics. ~Elye~

媒体 Twitter FacebookReddit上关注我获取有关移动开发等相关主题的小技巧和学习。 〜艾莉〜

翻译自: https://medium.com/mobile-app-development-publication/kotlin-koin-scope-illustrated-3bfa6c7ae98

史蒂夫科恩

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

史蒂夫科恩_科特琳·科恩范围 的相关文章

  • 如何在Python中每次运行脚本时增加变量?

    我有一个 Python 脚本 我想在每次运行时增加一个全局变量 这可能吗 使用外部文件很容易做到这一点 您可以创建一个函数来为您执行此操作 这样您就可以根据需要将多个文件用于多个变量 尽管在这种情况下您可能想要研究某种序列化并将所有内容存储
  • Python:合并嵌套列表

    初学者在这里 我有 2 个要合并的嵌套列表 list1 a b c d e f g h list2 p q r s t u v w 我正在寻找的输出是 list3 a p q b c r s d e t f g h u v w 这可以在没有
  • 将 unique_ptr 与 boost python 结合使用 - boost::shared_ptr 有效,但 unique_ptr 无效

    这可能与以下问题相同 Boost Python 没有 to python for std unique ptr https stackoverflow com questions 20590205 boost python no to py
  • 在 Spark-submit 上的 _find_and_load 中获取文件“”,第 991 行

    我目前使用的是Python 3 7 9 spark spark 2 4 6 bin hadoop2 6 在这个项目 venv 中 我的设置为 kafka python 2 0 2 pip 21 2 4 py4j 0 10 9 pyspark
  • Keras 中的 Tensorflow 自定义损失函数 - 张量循环

    我正在尝试在 Keras 中编写自定义损失函数 如下所示 Keras 中的自定义损失函数 https stackoverflow com questions 43818584 custom loss function in keras 我的
  • 登录 python + mod_wsgi 应用程序

    我在 apache 服务器上部署了一个 python Flask 应用程序 这是我的abc conf file WSGIDaemonProcess voting app threads 5 WSGIScriptAlias election
  • Pandas 无法读取使用 h5py 创建的 hdf5 文件

    当我尝试读取使用 h5py 创建的 HDF5 格式文件时 出现 pandas 错误 我想知道我是否只是做错了什么 import h5py import numpy as np import pandas as pd h5 file h5py
  • 向 list.extend() 传递不可迭代对象

    我正在创建一个公共方法来允许调用者将值写入设备 例如将其称为 write vals 由于这些值将实时输入 因此我希望通过允许用户输入列表或单个值来简化用户的生活 具体取决于他们需要写入的值的数量 例如 write to device 1 2
  • 如何开始使用“scipy”

    我之前安装过 Python 3 4 2 和 3 5 2 在这两种情况下 我都可以在 Idle 中涉足编写和测试代码 这给了我两个窗口 一个用于代码的 运行 窗口 一个用于交互和测试的 Shell 窗口 输出 抱歉 不确定术语是否正确 现在我
  • Pandas 数据框列总和并收集结果

    给定以下数据框 import pandas as pd p1 name willy age 11 interest Lego p2 name willy age 11 interest games p3 name zoe age 9 int
  • 如何在 Django 中创建多选框?

    我正在尝试创建多选框字段来自姜戈选择 2 https github com applegrew django select2库如下图所示 我使用了下一个代码 但它返回简单的选择多个小部件 我想我忘了补充一些东西 我的错误在哪里 有人可以告诉
  • Python:从字符串访问变量[重复]

    这个问题在这里已经有答案了 这可能是非常基本和简单的事情 我可能只是在谷歌上搜索错误的术语 但希望这里有人可以帮助我 我仍然是编程的初学者 这从这个问题中可能是显而易见的 我正在寻找一种从字符串访问变量的方法 像这样 A1 B1 C1 my
  • 使用 Python 3.7+ 中的 wfastcgi 以及 Numpy、Pandas 等在 IIS 上部署 Python Flask 应用程序

    使用 wfastcgi 在 IIS 上部署 python 3 7 Flask 或 Dash 应用程序时 有许多很棒的教程可以让 hello work 程序正常运行 例如 https medium com bilalbayasut deplo
  • matplotlib 轴标签偏移量的因素和变化

    在 matplotlib 中的轴刻度标签上 有两种可能的偏移量 factors and shifts 在右下角 1e 8 是一个 因子 1 441249698e1 是一个 移位 这里有很多答案展示了如何操纵两个都 matplotlib 将轴
  • 返回 OSError 异常类的子类实例的逻辑在哪里?

    我一直在寻找一些对某些人来说可能相对愚蠢的东西 但对我来说非常有趣 输入和输出错误已合并为OSError在 Python 3 3 中 异常类层次结构发生了变化 关于内置类的一个有趣的特性OSError是这样 它在传递时返回它的子类errno
  • 捕获 CommandOnCooldown 错误

    我正在制作一个有冷却时间的不和谐机器人 并且我正在尝试制作一个事件 当CommandOnCooldown发生错误时 机器人会通过私信告诉他们需要等待多长时间 这是我的代码 看起来一切正常 但它不知道 retry after 意味着什么 bo
  • 在 python 中将数组作为参数传递

    我是Python新手 现在我需要声明大小为 20 的数组并将该数组传递给函数 需要数组的函数如下 function args The args是一个输入function 谁能帮我 如何在 python 中传递数组 当你说 数组 时 我假设你
  • 如何从已安装的云端硬盘文件夹中永久删除?

    我编写了一个脚本 在每次迭代后将我的模型和训练示例上传到 Google Drive 以防发生崩溃或任何阻止笔记本运行的情况 如下所示 drive path drive My Drive Colab Notebooks models if p
  • 将 sudo 与 Python 脚本结合使用

    我正在尝试编写一个小脚本来在每次执行脚本时安装 VirtualBox 共享文件夹 我想用Python 来做这件事 因为我正在尝试学习它来编写脚本 问题是我需要特权才能启动挂载命令 我可以将脚本作为 sudo 运行 但我更喜欢它自己创建 su
  • 无法比较类型“ndarray(dtype=int64)”和“str”

    Example of data that I want to replace 数据具有以下属性 购买 V 高 高 中 低 维持 V 高 高 中 低 门 2 3 4 5 更多 2 4人以上 lug boot 小 中 大 安全性低 中高 这就是

随机推荐

  • 使用STM32CUBEIDE创建工程,点亮LED

    1 创建LED驱动文件 先在工程下新建一个文件夹命名为icode存放驱动程序 然后对每一个外设新建新的驱动文件夹 如驱动LED就新建文件夹led 然后在led文件夹下创建对应的头文件和源文件 即led h和led c 然后编写对应外设的驱动
  • X.509证书的使用

    总结一下如何使用X 509证书来保护我们的设备的数据传输 证书的签发 以下是证书签发的流程 为了更好的演示 我们需要分别创建两个根证书 并且用每个根证书来颁发一个客户端证书 这两个根证书分别为root 1 crt以及root 2 crt 对
  • Java上传下载ftp文件

    在Java中连接FTP服务器可以使用Apache Commons Net库提供的FTPClient类 以下是一个简单的示例代码 演示如何连接到FTP服务器 进行文件上传和下载操作 import org apache commons net
  • 【Windows上同时安装两个不同版本MYSQL】MySQL安装教程--5.7和8.0版本

    一 MySQL官网下载对应版本的zip文件 最新版本8 0 34下载链接 https dev mysql com downloads mysql MySQL 5 7下载链接 https downloads mysql com archive
  • vue中使用百度地图自定义信息窗口

    场景 点击地图上的标注的时候 希望可以显示自定义的信息弹窗 具体效果如下 注意 如果只是简单显示信息 则使用InfoWindow信息窗口或者标注本身的title属性即可 想自定义就使用infoBox自定义信息窗口工具 效果 效果图是GIF图
  • 【满分】【华为OD机试真题2023B卷 JS】矩阵最大值

    华为OD2023 B卷 机试题库全覆盖 刷题指南点这里 矩阵最大值 知识点矩阵数组 时间限制 1s 空间限制 32MB 限定语言 不限 题目描述 给定一个仅包含0和1的N N二维矩阵 请计算二维矩阵的最大值 计算规则如下 1 每行元素按下标
  • startx analyze

    1 xinit 在说明startx之前 我想我们应该先了解一下xinit 因为startx就是通过调用xinit启动X的 1 1 功能 当我们安装了Ubuntu后 默认就已经安装了xinit 它位于 usr bin下 xinit是一个二进制
  • RabbitMQ(四)消息Ack确认机制

    RabbitMQ 四 消息Ack确认机制 确认种类 RabbitMQ的消息确认有两种 消息发送确认 这种是用来确认生产者将消息发送给交换器 交换器传递给队列的过程中 消息是否成功投递 发送确认分为两步 一是确认是否到达交换器 二是确认是否到
  • AS 从SVN转向Git

    之前的项目都是用SVN 感觉SVN 还是挺不错的 但接触了Git后 才发现长江后浪推前浪 前浪死在沙滩上 果断抛弃了SVN 转向git的怀抱 虽然遇到了很多问题 但在同事的帮助下 至少能上传和check了 之后遇到git上的问题后 在写文章
  • js从数组中提取自己所需的数据

    1 场景一 人员选择相关问题 场景一 从人员选择数据中 提取已选的人员信息 selectedList为已选择的人员信息 只有id groupInfo接口返回的原始数据 所有人员信息 需要找出已选择的人员信息的具体信息 const group
  • 使用RBAC模型构建动态路由权限,交由前端动态渲染路由。

    根据RBAC模型生成动态路由并交给前端渲染 什么是RBAC模型 简单的RBAC模型数据库设计 后端处理动态的路由表信息 前端渲染路由的细节与注意 什么是RBAC模型 RBAC Role Based Access Control 模型是一种访
  • C++0基础教程

    还在苦恼找不到C 的教程吗 这篇文章搞定C 基础内容 前言 C 是一门编译型语言 是面向对象的 C 对语法的要求较高 且记忆量较大 但其运行速度较快 且编译过后是 exe的文件 可以直接运行 因此深受青睐 目录 前言 准备工作 C 源码文件
  • Chap3_数据预处理

    数据预处理 什么是数据预处理 数据分析算法的设计与选择需要考虑被处理数据的特征 数据质量过低或数据的形态不符合算法需求时 需要进行数据预处理工作 数据预处理是指对数据进行正式处理 计算 之前 根据后续数据计算的需求对原始数据集进行审计 清洗
  • 数据仓库建设及数据治理总结

    在谈数仓之前 先来看下面几个问题 数仓为什么要分层 用空间换时间 通过大量的预处理来提升应用系统的用户体验 效率 因此数据仓库会存在大量冗余的数据 不分层的话 如果源业务系统的业务规则发生变化将会影响整个数据清洗过程 工作量巨大 通过数据分
  • python使用 itchat结合图灵微信群机器人回复源码

    突然来了下兴致 又弄了个前几个月弄的微信群机器人 功能有好友之间的回复 群艾特后的回复 下面是源码 有更多的请看其他博文 coding utf 8 Time 2018 11 5 12 17 Author 蛇崽 Email 643435675
  • Qt::WindowFlags

    查了些资料 整理了一下 以备查询 枚举类型 Qt WindowFlags低位的一个字节用于定义窗口部件的窗口类型 Qt WindowFlags的高位字节定义了窗口提示 窗口提示能够进行位或操作 例如 Qt WindowContextHelp
  • K210学习篇(八)在MaixHub训练模型

    前言 本文着重于如何使用K210拍摄图片 并将图片上传到MaixHub平台进行模型训练 补充一下一些经验心得 比如一些训练参数的设置 在我们训练模型之前 我们需要获取一些数据集 其实也就是需要识别的物体图片 这里记得我们在获取数据集的时候
  • 获取shell返回值

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 使用command 二 使用function 总结 前言 shell获取返回值的方法有多种 这里介绍两种 第一种是直接执行command然后获取返回值 第
  • js歌词滚动效果

    目录 效果图展示 一 素材准备 1 歌词数据data js 借鉴了网上copy下来的歌词模板 2 图片准备 设置title效果 3 音频文件准备 二 html块 拓展 标签属性 三 设置scss样式 四 逻辑js块 拓展 使用到的audio
  • 史蒂夫科恩_科特琳·科恩范围

    史蒂夫科恩 学习Android开发 Learning Android Development If you are familiar with Dagger 2 you probably know that Scope an importa