概念
LayoutContainer
是一个用于自动解析布局并且自动通过findViewById
给对应id的View 进行初始化的接口。
应用场景
我们先来看看'kotlin-android-extensions'
这个插件,它会在 View,Activity 或者 Fragment 中生成一些额外的代码,然后就可以使用 XML 中定义的 id 来引用 View了。
参考:Kotlin Android Extensions: Say goodbye to findViewById (KAD 04)
但是如果我们的场景不是 View,Activity 或者 Fragment 的时候呢?就无法使用这个插件了。但是 kotlin 提供了 LayoutContainer
插件,它的工作原理和 'kotlin-android-extensions'
差不多也是生成一些额外的代码,目的就是为了生成findViewById 等代码。
如何使用
实现 LayoutContainer
并且给对应的 containerView
赋值。然后在需要的地方直接使用这个布局定义的 id(例如下面的llRoomMode) 来应用 View 即可,不需要再 findViewById。
class PartySettingsComponent(override var containerView: View? ) : LayoutContainer{
//随便写一个代码,找一个地方调用即可。
private fun initView() {
//加载一个 View 出来,并且赋值给 containerView (重要)
containerView = View.inflate(mRootComponent.activityContext, R.layout.view_dialog_party_settings, null)
//修改派对模式
llRoomMode.setOnClickListener {
mSettingDialog?.dismiss()
mProvider.onShowSwitchPartyMode()
}
}
在 app/build.gradle 添加如下代码,不然无法引用到引用的id
androidExtensions {
experimental = true
}
工作原理
反编译kotlin代码
要查看它是如何工作的就得反编译这个类了。
现在来关注一下它是如何帮我们实例化控件的,下面的代码是反编译后的代码,可以看到它会去调用 _$_findCachedViewById
来获取指定id对应的view对象。
((LinearLayout)this._$_findCachedViewById(id.llRoomMode)).setOnClickListener((OnClickListener)(new OnClickListener() {
public final void onClick(View it) {
BottomSheetDialog var10000 = PartySettingsComponent.this.mSettingDialog;
if (var10000 != null) {
var10000.dismiss();
}
PartySettingsComponent.this.mProvider.onShowSwitchPartyMode();
}
}));
_$_findCachedViewById 方法
从这个方法可以看出它优先去集合中获取,找不到就真正去 findViewById 然后再将其缓存起来,实现还是比较简单的。
public View _$_findCachedViewById(int var1) {
if (this._$_findViewCache == null) {
this._$_findViewCache = new HashMap();
}
//这里做了个缓存
View var2 = (View)this._$_findViewCache.get(var1);
if (var2 == null) {
View var10000 = this.getContainerView();
if (var10000 == null) {
return null;
}
//找不到就去getContainerView()中findViewById查找,这个就是我们上面 inflate 出来的布局了。
var2 = var10000.findViewById(var1);
this._$_findViewCache.put(var1, var2);
}
return var2;
}
本文是笔者学习之后的总结,方便日后查看学习,有任何不对的地方请指正。
记录于 2020年6月19号