前言
kotlin的by lazy关键字是很常用的,它表示延时初始化变量,只在第一次使用时才给它初始化。那么它是如何实现这种功能的呢?这篇文章从字节码和Java语言的角度揭密它的实现原理。
ViewModel和ViewBinding变量初始化过程
先举两个项目中最常见的例子:ViewModel和ViewBinding,了解一下为什么需要延时初始化。
看一段代码:
class MainActivity : AppCompatActivity() {
private val viewModel: MainViewModel by lazy {
ViewModelProviders.of(this).get(MainViewModel::class.java)
}
private val binding: ActivityMainBinding by lazy {
ActivityMainBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.i("MainActivity", "onCreate")
}
}
Jetpack库中的ViewModel和ViewBinding的使用是非常常见的,ViewModel和ViewBinding类型的变量都是需要延时初始化,不能在声明时初始化。ViewModel是因为内部需要依赖Activity的成员变量mApplication,而mApplication是在attach时给赋值的。ViewBinding的初始化需要依赖Window的layoutInflater变量,而Window变量也是在attach时赋值的。
先看ViewModel是如何初始化的,在以下ViewModelProviders.of方法里会调用checkApplication判断application是否为空,为空则抛出异常:
public class ViewModelProviders {
/**
* @deprecated This class should not be directly instantiated
*/
@Deprecated
public ViewModelProviders() {
}
private static Application checkApplication(Activity activity) {
Application application = activity.getApplication();
if (application == null) {
throw new IllegalStateException("Your activity/fragment is not yet attached to "
+ "Application. You can't request ViewModel before onCreate call.");
}
return application;
}
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull Fragment fragment, @Nullable Factory factory) {
Application application = checkApplication(checkActivity(fragment));
if (factory == null) {
factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}
return new ViewModelProvider(fragment.getViewModelStore(), factory);
}
mApplication是Activity的成员变量,它是在attach时赋值的:
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,

本文深入探讨了Kotlin中`by lazy`关键字的实现机制,通过字节码和Java代码的角度揭示其延时初始化的原理。在ViewModel和ViewBinding的例子中,`by lazy`确保了变量在首次使用时才进行初始化,避免了因依赖未准备好而导致的错误。分析了字节码后,发现`by lazy`将变量转换为`Lazy`类型,通过`Lazy`的`getValue`方法判断并执行初始化。此外,还展示了`by lazy`的Java实现,证实了字节码反编译后的等价性。
最低0.47元/天 解锁文章
606

被折叠的 条评论
为什么被折叠?



