Kotlin自动findViewById神器-LayoutContainer

概念

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号

你可能感兴趣的:(Kotlin自动findViewById神器-LayoutContainer)