第一次看
#kotlin #android #hilt #di

吞噬

从Google团队中提出了一个名为Hilt的新依赖注入库。它是在匕首库的顶部设计的,并提供了更简单,更少的样板API,以处理Android应用程序中的依赖项。第一次尝试,这是一个真正的改变游戏规则的人。因此,我们将简要介绍一下,然后讨论一些观点。

为什么要建造?

首先,匕首很难开始,尤其是对于初学者而言。其次,随着匕首的贬低,在Android中解决了一个新图书馆。它也比匕首少,使测试更简单。

匕首的问题 - android

长话短说,Android很难,@ContributesAndroidInjector使事情变得更加困难。以我本人的看法,这是一个有力的理由,要放弃匕首。忘记在那里添加依赖关系,并试图解决构建问题,给尝试使用它带来很多头痛。

是什么用刀柄改变了游戏?

如果我尝试用它来表达它,我会说它像应将其对待的Android类一样对待,正常类。在匕首,活动,碎片,工人是课堂上,但也是神秘的物体,与之合作。

非常可怕。

这篇文章假设读者知道匕首

快速开始使用

让我们从模块开始。由于它是在匕首顶部建造的,因此还有一些东西。让我们假设我们有一个例子:

@Module  
object MyAppScopeDependenciesModule{  
  @Provides  
  @Singleton  
  fun provideDependency1() : Dep1 = Dep1.builder().build()  

  @Provides  
  @Singleton  
  fun provideDependency2() : Dep2 = Dep2.builder().build()  
}

,让我们仅出于示例(应用程序级别范围)而创建一个组件:

@Singleton  
@Component(modules = [MyAppScopeDependenciesModule::class])  
interface MyApplicationComponent{  
  val dependency1: Dep1  
  val dependency2: Dep2  

  @Component.Factory  
  interface Factory{  
   fun create(application: Application): MyApplicationComponent  
  }  
}

让我们点击构建按钮,然后开始导入依赖项:

class MyApplication : Application(){  

  @Inject lateinit var dep1: Dep1  

  override fun onCreate(){  
    super.onCreate()  

    DaggerMyApplicationComponent.factory().create(this)  
  }  
}  

范围和模块之间的关系总是神秘的,他们从不关心检查匕首的注释处理器产生的内容。因此,我必须说,这是那些建造剑柄的人发现的。在匕首中,范围的模块与范围内的分量相连,如果这两个(或更多模块)相关。

,它提供了近0个信息。

现在,让我们尝试用刀柄构建上述示例:

@Module  
@InstallIn(ApplicationComponent::class)  
object MyAppScopeDependenciesModule{  
  @Provides  
  fun provideDependency1() : Dep1 = Dep1.builder().build()  

  @Provides  
  fun provideDependency2() : Dep2 = Dep2.builder().build()  
}

按下构建按钮之前,这就是您所需要的。

我的组件在哪里?

Hilt为您提供组件。无需创建组件或范围。考虑组件和范围合并在一起的组件和范围。实际上,这就是为什么HILT是游戏规则改变者的原因。 Hereis组件层次结构需要用于来自dagger.hilt.android.components.*的Android应用程序。基本上,您知道您的依赖性寿命,现在您知道要在哪里安装它。最后一步,让我们执行依赖注入:

@HiltAndroidApp  
class MyApplication : Application(){  

  @Inject lateinit var dep1: Dep1  

  override fun onCreate(){  
    super.onCreate()  
    ...  
  }  
}

另外,如果您想在活动,碎片,视图,服务或广播接收器中执行DI,那么AndroidInjection.inject(this)不再需要。相反,只需用@AndroidEntryPoint标记班级的顶部:

@AndroidEntryPoint  
class MainActivity : AppCompatActivity() {  
  // either comming from an ActivityComponent or ApplicationComponent  
  @Inject lateinit var dependency: Dependency  

  override fun onCreate() {  
    super.onCreate()  
    ...  
  }  
}

注射发生在onCreate()

那是最好的吗?

nope,Hilt最终也解决了ViewModels实例化过程的问题,通常,运行时并立即在构造函数中构建时间依赖关系。在使用之前,我曾经安装AssistedInject以正确地创建saveStateHandle,并且有一个关于如何做到这一点的full tutorial。但是,让我们做一些简单的简短演示:

class MyViewModel @AssistedInject constructor(  
  private val dep1: Dep1,  
  @Assisted private val saveStateHandle: SaveStateHandle  
){  

  @AssistedInject.Factory  
  interface Factory{  
    fun create(saveStateHandle: SaveStateHandle) : MyViewModel  
  }  
}

然后为其安装一个模块:

@AssistedModule  
@Module(includes = [AssistedInject_ViewModelModule::class])  
abstract class ViewModelModule

然后在AppComponent中露出视图模型:

@Component(...)  
interface AppComponent{  
  ...  
  val vmFactory: MyViewModel.Factory  
  ...  
}

之后,我可以在我的片段中快乐地拥有一个观点:

inline fun  Fragment.viewModelFactory(  
    crossinline provider: (SavedStateHandle) -> T  
) = viewModels {  
    object : AbstractSavedStateViewModelFactory(this, fragment.arguments ?: Bundle()) {  
        override fun  create(key: String, modelClass: Class, handle: SavedStateHandle): T =  
            provider(handle) as T  
    }  
}  

class HomeFragment : Fragment() {  

    private val myViewModel by viewModelFactory { Application.component().vmFactory.create(it) }  

    ...  
 }

有关此解决方案的更多详细信息,请检查上面提供的链接。

必须只为ViewModel做所有这些步骤很痛苦,更不用说AssistedInject还有很多事情要做(或者我可以使用Koin,但这不是目前的话题)。

使用刀柄,这很简单:

class EditorViewModel @ViewModelInject constructor(  
    private val playgroundRepository: PlaygroundRepository,  
    @Assisted private val savedStateHandle: SavedStateHandle  
) : ViewModel() {}

之后,不需要别的。只需像往常一样导入ViewModel:

//inside Fragment  
private val editorViewModel by viewModels()

请检查Hilt的文档以获取正确的依赖项。 ViewModelWorkManager解决方案作为分开的依赖项出现。有关更多信息,请检查here

Ondestroyview

就个人而言,我将使用刀柄作为Android的依赖性注入工具,这将是一个非常高兴的开发人员。与匕首相比,它使跟踪依赖性易于跟踪,易于启动和更少的样板。

但是,我在使用刀柄时注意到的一个缺点是,它在项目上增加了更多的抽象,您要么需要更多地了解代码生成,要么更好地不使用它。另外,忘记执行di为AndroidInjection.inject(this)DaggerMComponent.builder().build().inject(this)并用@AndroidEntryPointis注释课程仍然很棘手,无论哪种方式,您都会忘记。但是,这没有问题,因为该错误将在构建时间产生。

尽管如此,它看起来很有希望。

ondestroy

我希望我简要介绍一下,以开始使用刀柄,还对此发表了一些意见。 Android并不是一个简单的框架/库,可以使用的每个工具越来越多地配置,这始终是一个巨大的头痛。因此,我很高兴Google团队引入了Hilt。对于这里的所有匕首粉丝来说,Hilt是对所有抱怨匕首复杂性的人的强烈论点。

Stavro Xhardha