首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >Android + Kotlin + Hilt:注入静态方法类

Android + Kotlin + Hilt:注入静态方法类
EN

Stack Overflow用户
提问于 2022-07-30 05:53:41
回答 1查看 455关注 0票数 1

我不太清楚向静态方法助手类(比如自定义类)注入的最佳方法是什么。

我对Kotlin有点陌生,正如我所了解的,我们可以通过两种方式静态地访问一个方法:

  1. 对象类。
  2. 类+同伴对象。

首先,我不确定哪一个是最推荐的(如果有关于此的最佳实践),但是当需要将依赖项注入静态方法类时,我的“问题”就出现了。

让我们来举一个简单的例子:

我有一个名为AWUtils的静态方法类(虽然还没有决定它应该是对象类还是有伴生对象的类,这很可能取决于推荐的注入机制),接下来的方法如下:

代码语言:javascript
运行
AI代码解释
复制
fun setAmpersand2Yellow(text2Replace: String, target: String): String {
    return text2Replace.replace(
        target, "<span style=\"color:" +
                app.drawerFooterColor + ";\">" + target + "</span>"
    )
}

在这里,app是我的AppSettings类的实例,它保存了所有的应用程序配置,所以,正如您所看到的,setAmpersand2Yellow需要AppSettings,当然,我不会以任何方式将它作为参数传递,因此它是AWUtils依赖的。

为静态方法使用AWUtils作为伴随对象的类,据我所知,我不能直接将AppSettings注入公司对象(至少我不能进行构造函数注入,如果我错了请告诉我),如果我注入伙伴对象父类(AWUtils)构造函数,那么我不知道如何从伙伴对象本身(子构造器)访问这些依赖项。

如果我在AWUtils中使用字段注入作为类,那么它会比后发字段更抱怨没有初始化,而且我不知道如何处理这个问题,因为据我所知,延迟字段是在onCreate中初始化的,这在这类类中并不存在。

另一种可能是在调用方法之前使用带有字段的对象并以静态方式设置调用方的依赖项值,例如:

代码语言:javascript
运行
AI代码解释
复制
object AWUtils {

    var app: AppSettings? = null

    fun setAmpersand2Yellow(text2Replace: String, target: String): String {
        return text2Replace.replace(
            target, "<span style=\"color:" +
                    app.drawerFooterColor + ";\">" + target + "</span>"
        )
    }
}

@AndroidEntryPoint
class OtherClass 
@Inject constructor(private val app: AppSettings) {
    
    fun AnyFunction() {
        var mystr = "whatever"
        AWUtils.app = app
        var yellowStr = AWUtils.setAmpersand2Yellow(myStr)
    }
}

最后,我不确定如何向静态方法类提供依赖关系,以及应该选择哪种形式的“静态”类。

编辑1:

除了我的ApSettings类之外,我还需要一个上下文,例如在下一个isTablet方法中:

代码语言:javascript
运行
AI代码解释
复制
val isTablet: String
    get() {
        return ((context.resources.configuration.screenLayout
                and Configuration.SCREENLAYOUT_SIZE_MASK)
                >= Configuration.SCREENLAYOUT_SIZE_LARGE)
    }

最后,我需要一个上下文和我的AppSettings (或任何其他自定义类)被注入到一个带有静态方法的类中。

编辑2:

我可以(从活动中)做:

代码语言:javascript
运行
AI代码解释
复制
AWUtils.context = this
AWUtils.app = app
var isTablet = AWUtils.isTablet

而且它可以工作,但是需要为两个字段(或更多的字段)分配值,每次我需要调用静态方法时,我更希望以任何方式注入字段。

这就是依赖注入的目的,不是吗?

编辑3:我开始对Hilt感到厌烦了,我们应该创造的东西是为了简化我们的生活,只会使我们的编程生活变得更加复杂。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-30 13:58:34

正如您在注释中所阐明的那样,您希望您的utils类可以轻松地通过代码库访问,因此这个答案将集中在这一点和您最初的问题上。

我对Kotlin有点陌生,正如我所了解的,我们可以通过两种方式静态地访问一个方法: object类或class +伴侣对象。

科特林没有Java风格的静力学。其背后的一个理由是鼓励更可维护的编码实践。静态方法和静态类也是测试代码的噩梦。

在Kotlin中,您可以使用一个对象(但是类+伙伴对象将以同样的方式工作)

代码语言:javascript
运行
AI代码解释
复制
object AWUtils {
    lateinit var appContext: Context
    lateinit var appSettings: AppSettings

    fun initialize(
        appContext: Context,
        appSettings: AppSettings,
        // more dependencies go here
    ) {
        this.appContext = appContext
        this.appSettings = appSettings
        // and initialize them here
    }

    val isTablet: Boolean
        get() = ((appContext.resources.configuration.screenLayout
                and Configuration.SCREENLAYOUT_SIZE_MASK)
                >= Configuration.SCREENLAYOUT_SIZE_LARGE)


    fun setAmpersand2Yellow(text2Replace: String, target: String): String {
        return text2Replace.replace(
            target, "<span style=\"color:" +
                    appSettings.drawerFooterColor + ";\">" + target + "</span>"
        )
    }
}

由于这个对象应该可以在整个应用程序中访问,所以应该尽快初始化它,因此在Application.onCreate中是如此。

代码语言:javascript
运行
AI代码解释
复制
@HiltAndroidApp
class Application : android.app.Application() {
    // you can inject other application-wide dependencies here
    // @Inject
    // lateinit var someOtherDependency: SomeOtherDependency

    override fun onCreate() {
        super.onCreate()

        // initialize the utils singleton object with dependencies
        AWUtils.initialize(applicationContext, AppSettings())
    }

现在,在应用程序代码中的任何地方,您都可以使用AWUtilsAppSettings

代码语言:javascript
运行
AI代码解释
复制
class OtherClass { // no need to inject AppSettings anymore
    
    fun anyFunction() {
        val mystr = "whatever"
        val yellowStr = AWUtils.setAmpersand2Yellow(myStr)

        // This also works
        if (AWUtils.isTablet) {
            // and this as well
            val color = AWUtils.appSettings.drawerFooterColor
        }        
    }
}

Kotlin中还有另一种编写助手/util函数的方法,称为扩展函数

您的isTablet检查可以编写为如下扩展函数

代码语言:javascript
运行
AI代码解释
复制
// This isTablet() can be called on any Configuration instance
// The this. part can also be omitted
fun Configuration.isTablet() = ((this.screenLayout
        and Configuration.SCREENLAYOUT_SIZE_MASK)
        >= Configuration.SCREENLAYOUT_SIZE_LARGE)

// This isTablet() can be called on any Resources instance 
fun Resources.isTablet() = configuration.isTablet()

// This isTablet() can be called on any Context instance
fun Context.isTablet() = resources.isTablet()

有了上述扩展函数之后,AWUtils内部的实现将简化为

代码语言:javascript
运行
AI代码解释
复制
    val isTablet: Boolean
        get() = appContext.isTablet()

在(或引用)实现Context的任何类中,例如ApplicationActivityService等,您可以简单地调用isTablet()

代码语言:javascript
运行
AI代码解释
复制
class SomeActivity : Activity() {
    fun someFunction() {
        if (isTablet()) {
            // ...
        }
    }
}

在其他以某种方式可用ContextResources的地方,您可以简单地调用resources.isTablet()

代码语言:javascript
运行
AI代码解释
复制
class SomeFragment : Fragment() {
    fun someFunction() {
        if (resources.isTablet()) {
            // ...
        }
    }
}

编辑3:我开始对Hilt感到厌烦了,我们应该创造的东西是为了简化我们的生活,只会使我们的编程生活变得更加复杂。

是的,希尔特专注于构造函数注入,并且只能在非常有限的情况下,在非常有限的情况下,只在带有@AndroidEntryPoint注解的Android类中,以及在用@HiltAndroidApp注释时在类内扩展Application类。

@AndroidEntryPoint文档

标记一个Android组件类,以便使用标准的Hilt组件进行注入。目前,这支持活动、片段、视图、服务和广播接收器。

如果您觉得需要大量的字段注入,因为您正在使用Kotlin中的“静态”-like对象,请考虑在下一个项目中使用Koin而不是Hilt。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73176180

复制
相关文章
ggplot2再话箱线图之几何填充
❝VIP群里有观众老爷询问如何对箱线图进行几何形状填充,那么今天就来具体介绍一番;在原有的基础上做了一些小的改动也许恰好您正好有此特殊需求,需要着重体会八个字「变实为虚,变虚为实」,希望对各位观众老爷有所帮助;下面来看具体案例; ❞ 加载R包 library(tidyverse) library(ggsci) library(ggprism) library(rstatix) library(ggpubr) library(ggpmisc) library(ggpattern) 加载数据 gapminde
R语言数据分析指南
2022/09/21
3870
ggplot2再话箱线图之几何填充
脑组织中的梯度
近年来,研究脑组织空间变化或梯度的新方法和应用兴起,补充了在识别和绘制离散脑区和宏观功能社区方面取得的进展。在人类和非人灵长类动物死后细胞结构的早期分析中已经强调了这一点,最近的神经影像学和网络神经科学研究在绘制人类和非人类大脑的空间梯度方面取得了重大进展。
悦影科技
2022/06/20
5650
PyTorch中的梯度累积
我们在训练神经网络的时候,超参数batch_size的大小会对模型最终效果产生很大的影响,通常的经验是,batch_size越小效果越差;batch_size越大模型越稳定。理想很丰满,现实很骨感,很多时候不是你想增大batch_size就能增大的,受限于显存大小等因素,我们的batch_size往往只能设置为2或4,否则就会出现"CUDA OUT OF MEMORY"(OOM)报错。如何在有限的计算资源下,采用更大的batch_size进行训练,或者达到和大batch_size一样的效果?这就是梯度累加(Gradient Accumulation)技术了
mathor
2021/07/28
1.5K0
Tensorflow中的梯度裁剪
本文简单介绍梯度裁剪(gradient clipping)的方法及其作用,不管在 RNN 或者在其他网络都是可以使用的,比如博主最最近训练的 DNN 网络中就在用。
狼啸风云
2020/01/13
2.9K0
Tensorflow中的梯度裁剪
ggplot2学习笔记:加拿大地图按省界填充颜色
参考文献 1 https://gis.stackexchange.com/questions/303666/using-gsimplify-in-chloropleth 2 https://kieranhealy.org/blog/archives/2018/12/09/canada-map/ 完整代码 library(raster) library(sf) library(ggplot2) library(viridis) library(rgdal) canada_raw <- readOGR(dsn
用户7010445
2020/03/03
1.1K0
ggplot2画密度分布图按取值范围填充不同的颜色
参考链接是 ggplot2 area plot : Quick start guide - R software and data visualization - Easy Guides - Wiki - STHDA
用户7010445
2020/12/08
2.7K0
ggplot2画密度分布图按取值范围填充不同的颜色
Numpy中的填充,np.pad()
在卷积神经网络中,为了避免因为卷积运算导致输出图像缩小和图像边缘信息丢失,常常采用图像边缘填充技术,即在图像四周边缘填充0,使得卷积运算后图像大小不会缩小,同时也不会丢失边缘和角落的信息。在Python的numpy库中,常常采用numpy.pad()进行填充操作,具体分析如下:
种花家的奋斗兔
2020/11/13
2K0
Numpy中的填充,np.pad()
ggplot2 中 scale 的使用
ggplot画图是画图中的战斗机,但是往往在我们用ggplot2画图时候,需要根据需求更改坐标,图例等,最常见的就是更改x,y坐标系的名称。在ggplot2中,坐标系与比例尺和参考线是自动生成的,并且生成得很好。
Jamesjin63
2022/10/25
1.8K0
ggplot2 中 scale 的使用
ggplot2中ylim的坑
​在ggplot2中很容易出现一个修改坐标轴范围的问题,喜欢用ggplot2画图的需要注意一下。ylim和coord_cartesian都是调整坐标轴范围,但是它们的结果是有可能不一样的,看下面的一个例子:
生信编程日常
2020/04/01
1.2K0
ggplot2中ylim的坑
机器学习中的梯度下降法
机器学习中的大部分问题都是优化问题,而绝大部分优化问题都可以使用梯度下降法(Gradient Descent)处理,那么搞懂什么是梯度,什么是梯度下降法就非常重要。 提到梯度,就必须从导数(deriv
海天一树
2018/04/24
6750
机器学习中的梯度下降法
Openlayers4中图片填充的实现
概述 本文讲述如何在Openlayers实现面状要素的图片填充。 实现后 实现代码 var bounds = [73.4510046356223, 18.1632471876417, 134.
牛老师讲GIS
2018/10/23
2K0
Openlayers4中图片填充的实现
ggplot2中的position参数解析
这是position_dodge()的简写形式,它会自动计算需要的dodge宽度。不能设置preserve参数。
R语言数据分析指南
2023/09/24
7030
ggplot2中的position参数解析
向容器中填充元素---fill
利用fill可以将容器区间填充为指定的值 属于算术生成算法一类的小型算法-----需要包含头文件numeric
大忽悠爱学习
2021/03/02
6470
向容器中填充元素---fill
ThinkPHP中自动填充日期时间
如果是用自己的函数那就要用callback,第二个参数默认当前模块能调用的方法;用function的话第二个参数为函数名,而这个函数可以是PHP自带的,也可以是你自己写的
PM吃瓜
2019/08/13
1.4K0
pytorch中loss函数及其梯度的求解
Cross entropy loss可用于二分类(binary)和多分类(multi-class)问题,在使用时常与softmax搭配使用,后文继续讲解。
用户6719124
2019/11/17
2.4K0
神经网络中的梯度优化算法
对于大规模的神经网络训练我们经常采用mini-batch Gradient Descent,但是在MBGD中如何选择合适的学习率是一个非常困难的问题。Learning Rate设置太小会导致神经网络收敛缓慢,Learning Rate设置太大可能导致神经网络在最小值附近波动甚至发散。
YoungTimes
2022/04/28
4360
神经网络中的梯度优化算法
图解集成学习中的梯度提升思想
机器学习(ML)中的一个关键步骤是选择适合数据的最佳算法,根据数据中的一些统计数据和可视化信息,机器学习工程师将选择最佳算法。假设数据如下图所示,现在将其应用于回归示例:
用户3578099
2019/08/15
6210
图解集成学习中的梯度提升思想
图表中包含负值的双色填充技巧
今天教大家怎么在Excel里制作带负值的双色填充图表 正负值双色填充 ▼ 通常如果数据中带负值 默认的图表输出虽然能够显示负值 但是负值颜色与正值并没有任何区别 视觉效果大打折扣 今天来教大家怎么处理
数据小磨坊
2018/04/10
2.6K0
图表中包含负值的双色填充技巧
深度学习中的参数梯度推导(三)上篇
在深度学习中的参数梯度推导(二)中,我们总结了经典而基础的DNN的前向和反向传播。在本篇(上篇),我们将介绍另一经典的神经网络CNN的前向传播,并在下篇中介绍推导其反向传播的相关公式。
灯塔大数据
2020/08/17
1K0
点击加载更多

相似问题

注入实例的Guice空指针异常

11

google guice注入空

11

Guice注入空检查?

10

使用guice注入和参与者抛出空指针

30

Guice +泽西集成注入空对象

14
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文