有一个房间道,
@Dao
public abstract class AccountDao {
@Query("SELECT * FROM Account LIMIT 0,1")
public abstract Account readAccount();
}
下面的示例中get()
和by lazy
之间有什么区别吗?
open val account: LiveData<Account>
get() = accountDao.readAccount()
open val account: LiveData<Account> by lazy { accountDao.readAccount() }
答案 0 :(得分:10)
不同之处在于函数主体(accountDao.readAccount()
)将执行多少次。
lazy
委托将在第一次访问lambda时执行一次,并记住结果。如果再次调用,则返回该缓存的结果。
另一方面,定义getter(get()
)将每次执行函数主体,每次都返回一个新结果。
例如,假设我们有一个名为Foo
的类,它同时具有一个getter和一个惰性值:
class Foo {
val getterVal: String
get() = System.nanoTime().toString()
val lazyVal: String by lazy { System.nanoTime().toString() }
}
然后使用它:
fun main() {
with(Foo()) {
repeat(2) {
println("Getter: $getterVal")
println("Lazy: $lazyVal")
}
}
}
对我来说,它打印:
Getter: 1288398235509938
Lazy: 1288398235835179
Getter: 1288398235900254
Lazy: 1288398235835179
我们可以看到getter每次都返回一个新计算的值,而lazy版本则返回相同的缓存值。
答案 1 :(得分:1)
除了托德的答案:
是的,LiveData
个对象也有所不同。每次调用accountDao.readAccount()
都会导致不同 LiveData
对象。这确实很重要,尽管事实上,所有返回的LiveData
都会在Account
实体中的每次更改时得到更新。让我解释这些例子:
by lazy
正如Todd所提到的,lazy
委托中的块将被执行一次,第一次访问account
属性时,结果将被缓存并在每次下一次访问时返回。因此,在这种情况下,将创建一个LiveData<Account>
对象。 Kotlin生成的字节码等效于Java:
public class Activity {
private Lazy account$delegate
public LiveData<Account> getAccount() {
return account$delegate.getValue();
}
}
get()
通过创建自定义account
属性的getter并在内部调用accountDao.readAccount()
,您在LiveData<Account>
属性的每次访问中都会得到不同的account
对象。再一次,在Java的Kotlin中为这种情况生成的字节码或多或少是这样的:
public class Activity {
public LiveData<Account> getAccount() {
return accountDao.readAccount();
}
}
因此,您可以看到,使用惰性属性会为此属性生成一个后备字段,而使用自定义getter会为accountDao.readAccount()
调用创建包装方法。
哪种方法取决于您的需要。我想说的是,如果您只需要获得LiveData
一次,则应该使用get()
,因为在这种情况下不需要后备字段。但是,如果您要在代码中的多个位置访问LiveData
,也许更好的方法是使用by lazy
并仅创建一次。