热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

android对象初始化注释器,【译】kotlinAndroidFrameworks使用注释处理(五)

本文转自本人blog,更多关于kotlin详情点击本人blog本教程介绍如何在Kotlin流行的Android框架和库中使用依赖注释处理。Android世界有许多流行的框架

本文转自本人blog,更多关于kotlin详情点击本人blog

本教程介绍如何在Kotlin流行的Android框架和库中使用依赖注释处理。

Android世界有许多流行的框架,简化了开发。如果你在Kotlin开发,你可以使用相同的框架,就像在Java中一样容易。本教程提供了示例并突出显示了设置中的差异。

我们将看Dagger,Butterknife,Data Binding,Auto-parcel和DBFlow(其他框架可以类似的设置)。所有这些框架通过注释处理工作:您注释代码以为您生成样板代码。注释允许隐藏所有的详细信息并保持简单的代码,如果您需要了解运行时实际发生的情况,可以查看生成的代码。请注意,所有这些框架都是用Java生成源代码,而不是Kotlin。

在Kotlin中,使用Kotlin Annotation处理工具(kapt)而不是annotationProcessor来指定类似于Java的依赖关系。

Dagger(匕首)

Dagger是一个依赖注入框架。 如果您还不熟悉,可以阅读其用户指南。 我们已经将本指南中介绍的 the coffee example示例转换为Kotlin,您可以在这里找到结果。 Kotlin代码看起来几乎相同; 您可以在一个文件中浏览整个示例。

和Java一样,你使用@Inject来注释Dagger使用的构造函数来创建一个类的实例。 Kotlin有一个简短的语法来同时声明一个属性和一个构造函数参数。 要注释构造函数,请明确使用构造函数关键字,并在其之前放置@Inject注释:

class Thermosiphon

@Inject constructor(

private val heater: Heater

) : Pump {

// ...

}

注释方法看起来完全一样。 在下面的示例中,@Binds确定在需要Pump时使用Thermosiphon对象,@Provides指定构建Heater 的方式,@Singleton指出应在整个位置使用相同的Heater :

@Module

abstract class PumpModule {

@Binds

abstract fun providePump(pump: Thermosiphon): Pump

}

@Module(includes = arrayOf(PumpModule::class))

class DripCoffeeModule {

@Provides @Singleton

fun provideHeater(): Heater = ElectricHeater()

}

@Module-annotated类定义了如何提供不同的对象。 请注意,当您将注释参数作为可变参数传递时,必须将其显式包装到arrayOf中,如上面的@Module(includes = arrayOf(PumpModule :: class))。

要为该类型生成一个依赖注入的实现,请使用@Component为其注释。 生成的类将具有此类型的名称,如DaggerCoffeeShop所示:

@Singleton

@Component(modules = arrayOf(DripCoffeeModule::class))

interface CoffeeShop {

fun maker(): CoffeeMaker

}

fun main(args: Array) {

val coffee = DaggerCoffeeShop.builder().build()

coffee.maker().brew()

}

Dagger生成一个CoffeeShop的实现,允许你获得一个完全注入的CoffeeMaker。 如果您在IDE中打开项目,则可以导航并查看DaggerCoffeeShop的实现。

我们观察到,当您切换到Kotlin时,注释您的代码几乎没有改变。 现在让我们看看应该对构建脚本进行哪些更改。

在Java中,您将Dagger指定为annotationProcessor(或apt)依赖项:

dependencies {

...

annotationProcessor "com.google.dagger:dagger-compiler:$dagger-version"

}

在Kotlin中,您必须添加kotlin-kapt插件来启用kapt,然后用kapt替换annotationProcessor:

apply plugin: 'kotlin-kapt'

dependencies {

...

kapt "com.google.dagger:dagger-compiler:$dagger-version"

}

就这样! 请注意,kapt也会处理您的Java文件,所以您不需要保留annotationProcessor依赖关系。

示例项目的完整构建脚本可以在这里找到。 您也可以查看Android示例的转换后的代码。

ButterKnife

ButterKnife允许将视图直接绑定到字段,而不是调用findViewById。

请注意,Kotlin Android Extensions插件(自动捆绑到Android Studio中的Kotlin插件)解决了同样的问题:用简洁直接的代码替换findViewById。 考虑使用它,除非你已经使用ButterKnife并且不想迁移。

您可以像使用Java一样使用Kotlin的ButterKnife。 首先看看Gradle构建脚本中的更改,然后突出显示代码中的一些差异。

在您使用的Gradle依赖关系中添加kotlin-kapt插件并用kapt替换annotationProcessor:

apply plugin: 'kotlin-kapt'

dependencies {

...

compile "com.jakewharton:butterknife:$butterknife-version"

kapt "com.jakewharton:butterknife-compiler:$butterknife-version"

}

我们已经将ButterKnife样本转换为Kotlin。 结果代码可以在这里找到。

让我们来看看发生了什么变化。 在Java中,您注释了该字段,并将其与相应的视图绑定:

@BindView(R2.id.title) TextView title;

在Kotlin你不能直接使用字段,你使用属性。 您注释该属性:

@BindView(R2.id.title)

lateinit var title: TextView

@BindView注释被定义为只应用于字段,但是Kotlin编译器理解并注释了在注释应用于整个属性时引擎盖下的相应字段。

请注意,lateinit修饰符如何在创建对象之后(在构造函数调用之后)声明一个已初始化的非null类型。 没有lateinit ,你必须声明一个 nullable type 的类型并添加额外的可空性检查。

您还可以使用ButterKnife注释将方法配置为侦听器:

@OnClick(R2.id.hello)

internal fun sayHello() {

Toast.makeText(this, "Hello, views!", LENGTH_SHORT).show()

}

此代码指定要在“hello”按钮单击上执行的操作。 请注意,对于lambdas,这段代码看起来相当简洁直接写在Kotlin中:

hello.setOnClickListener {

toast("Hello, views!")

}

toast函数在Anko库中定义。

Data Binding(数据绑定)

Data Binding Library允许您以简明的方式将应用程序数据绑定到布局。

使用与Java中相同的配置启用该库:

android {

...

dataBinding {

enabled = true

}

}

要使它与Kotlin类一起工作,请添加kapt依赖项:

apply plugin: 'kotlin-kapt'

dependencies {

kapt "com.android.databinding:compiler:$android_plugin_version"

}

当你切换到Kotlin时,你的xml布局文件根本不会改变。 例如,您可以使用数据中的变量来描述可能在布局中使用的变量。 你可以声明一个Kotlin类型的变量:

您使用@ {}语法来编写表达式,现在可以引用Kotlin属性:

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:src="@{data.imageUrl}"

android:contentDescription="@string/image" />

请注意,数据绑定表达式语言使用与Kotlin:data.imageUrl相同的语法来引用属性。 在Kotlin中,即使getProp()是Java方法,您也可以编写v.prop而不是v.getProp()。 同样,不要直接调用setter,您可以使用一个赋值:

class MainActivity : AppCompatActivity() {

// ...

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

val binding: ActivityMainBinding =

DataBindingUtil.setContentView(this, R.layout.activity_main)

binding.data = weather

// the same as

// binding.setData(weather)

}

}

您可以绑定侦听器以在发生特定事件时运行操作:

android:text="@string/next"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:onClick="startOtherActivity" />

这里startOtherActivity是我们的MainActivity中定义的一个方法:

class MainActivity : AppCompatActivity() {

// ...

fun startOtherActivity(view: View) = startActivity()

}

此示例使用实用程序函数startActivity创建一个没有数据的意图,并启动一个来自Anko库的新活动。 要传递一些数据,你可以说startActivity (“KEY”到“VALUE”)。

请注意,不像以下示例中那样在xml中声明lambda表达式,您可以直接在代码中绑定动作:

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:onClick="@{() -> presenter.onSaveClick(task)}" />

// the same logic written in Kotlin code

button.setOnClickListener { presenter.onSaveClick(task) }

在最后一行中,button由使用Kotlin Android Extensions插件的id引用。 考虑使用这个插件作为替代方案,它允许您在代码中保留绑定逻辑并同时具有简洁的语法。

你可以在这里找到一个示例项目。

DBFlow

DBFlow是一个SQLite库,它简化了与数据库的交互。 它很大程度上依赖于注释处理。

要在Kotlin中使用它,请使用kapt配置注释处理依赖关系:

apply plugin: 'kotlin-kapt'

dependencies {

kapt "com.github.raizlabs.dbflow:dbflow-processor:$dbflow_version"

compile "com.github.raizlabs.dbflow:dbflow-core:$dbflow_version"

compile "com.github.raizlabs.dbflow:dbflow:$dbflow_version"

}

以下是如何配置DBFlow的详细指南。

如果您的应用程序已经使用DBFlow,则可以安全地将Kotlin引入您的项目。 您可以逐渐将现有代码转换为Kotlin(确保一路编译)。 转换后的代码与Java没有多大差别。 例如,声明一个表与Java非常相似,但有一点区别,即必须明确指定属性的默认值:

@Table(name="users", database = AppDatabase::class)

class User : BaseModel() {

@PrimaryKey(autoincrement = true)

@Column(name = "id")

var id: Long = 0

@Column

var name: String? = null

}

除了将现有功能转换为Kotlin外,您还可以享受Kotlin特定的支持。 例如,您可以将表声明为数据类:

@Table(database = KotlinDatabase::class)

data class User(@PrimaryKey var id: Long = 0, @Column var name: String? = null)

DBFlow定义了一系列扩展,使其在Kotlin中的使用更具惯用性,您可以在您的依赖中包含这些扩展:

dependencies {

compile "com.github.raizlabs.dbflow:dbflow-kotlinextensions:$dbflow_version"

}

这使您可以通过类似LINQ的C#语法来表达查询,使用lambdas为异步计算编写更简单的代码等等。 在这里阅读所有细节。

您可以浏览转换后的示例应用程序。

Auto-Parcel

Auto-Parcel允许为使用@AutoValue注解的类生成Parcelable值。

当您指定依赖项时,您再次使用kapt作为注释处理程序来处理Kotlin文件:

apply plugin: 'kotlin-kapt'

dependencies {

...

kapt "frankiesardo:auto-parcel:$latest-version"

}

转换后的样本可以在这里找到。

您可以使用@AutoValue注释Kotlin类。 我们来看看为其生成Parcelable实现的转换后的Address类:

@AutoValue

abstract class Address : Parcelable {

abstract fun coordinates(): DoubleArray

abstract fun cityName(): String

companion object {

fun create(coordinates: DoubleArray, cityName: String): Address {

return builder().coordinates(coordinates).cityName(cityName).build()

}

fun builder(): Builder = `$AutoValue_Address`.Builder()

}

@AutoValue.Builder

interface Builder {

fun coordinates(x: DoubleArray): Builder

fun cityName(x: String): Builder

fun build(): Address

}

}

Kotlin没有静态方法,所以它们应该放置在伴随对象中companion object。 如果您仍然想从Java代码中使用它们,请使用@JvmStatic对其进行注释。

如果您需要访问Kotlin中名称不是有效标识符的Java类或方法,则可以使用反引号(`)字符来转义该名称,就像访问生成的类“$ AutoValue_Address”一样。

总体而言,转换后的代码看起来与原始Java代码非常相似。



推荐阅读
  • vue使用
    关键词: ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文讨论了一个数列求和问题,该数列按照一定规律生成。通过观察数列的规律,我们可以得出求解该问题的算法。具体算法为计算前n项i*f[i]的和,其中f[i]表示数列中有i个数字。根据参考的思路,我们可以将算法的时间复杂度控制在O(n),即计算到5e5即可满足1e9的要求。 ... [详细]
  • 开发笔记:Dagger2 探索记3——两大进阶组件
        今天要讲的时@Scope这个组件。为什么说它是进阶组件,就是因为它基本上没作用,但在理解了基本组件之后又必须用到。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文介绍了最长上升子序列问题的一个变种解法,通过记录拐点的位置,将问题拆分为左右两个LIS问题。详细讲解了算法的实现过程,并给出了相应的代码。 ... [详细]
author-avatar
87年的第一场雪
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有