Kotlin自動(dòng)findViewById神器-LayoutContainer

概念

LayoutContainer 是一個(gè)用于自動(dòng)解析布局并且自動(dòng)通過(guò)findViewById給對(duì)應(yīng)id的View 進(jìn)行初始化的接口。

應(yīng)用場(chǎng)景

我們先來(lái)看看'kotlin-android-extensions'這個(gè)插件,它會(huì)在 View,Activity 或者 Fragment 中生成一些額外的代碼,然后就可以使用 XML 中定義的 id 來(lái)引用 View了。

參考:Kotlin Android Extensions: Say goodbye to findViewById (KAD 04)

但是如果我們的場(chǎng)景不是 View,Activity 或者 Fragment 的時(shí)候呢?就無(wú)法使用這個(gè)插件了。但是 kotlin 提供了 LayoutContainer 插件,它的工作原理和 'kotlin-android-extensions' 差不多也是生成一些額外的代碼,目的就是為了生成findViewById 等代碼。

如何使用

實(shí)現(xiàn) LayoutContainer 并且給對(duì)應(yīng)的 containerView 賦值。然后在需要的地方直接使用這個(gè)布局定義的 id(例如下面的llRoomMode) 來(lái)應(yīng)用 View 即可,不需要再 findViewById。

class PartySettingsComponent(override var containerView: View? ) : LayoutContainer{
    //隨便寫(xiě)一個(gè)代碼,找一個(gè)地方調(diào)用即可。
    private fun initView() {
       
        //加載一個(gè) View 出來(lái),并且賦值給 containerView (重要)
        containerView = View.inflate(mRootComponent.activityContext, R.layout.view_dialog_party_settings, null)
        
        //修改派對(duì)模式
        llRoomMode.setOnClickListener {
            mSettingDialog?.dismiss()
            mProvider.onShowSwitchPartyMode()
        }
        
        }

在 app/build.gradle 添加如下代碼,不然無(wú)法引用到引用的id

androidExtensions {
    experimental = true
}

工作原理

反編譯kotlin代碼

要查看它是如何工作的就得反編譯這個(gè)類(lèi)了。

現(xiàn)在來(lái)關(guān)注一下它是如何幫我們實(shí)例化控件的,下面的代碼是反編譯后的代碼,可以看到它會(huì)去調(diào)用 _$_findCachedViewById 來(lái)獲取指定id對(duì)應(yīng)的view對(duì)象。


((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 方法

從這個(gè)方法可以看出它優(yōu)先去集合中獲取,找不到就真正去 findViewById 然后再將其緩存起來(lái),實(shí)現(xiàn)還是比較簡(jiǎn)單的。

public View _$_findCachedViewById(int var1) {
   if (this._$_findViewCache == null) {
      this._$_findViewCache = new HashMap();
   }
   //這里做了個(gè)緩存
   View var2 = (View)this._$_findViewCache.get(var1);
   if (var2 == null) {
      View var10000 = this.getContainerView();
      if (var10000 == null) {
         return null;
      }
      //找不到就去getContainerView()中findViewById查找,這個(gè)就是我們上面 inflate 出來(lái)的布局了。
      var2 = var10000.findViewById(var1);
      this._$_findViewCache.put(var1, var2);
   }
   return var2;
}

本文是筆者學(xué)習(xí)之后的總結(jié),方便日后查看學(xué)習(xí),有任何不對(duì)的地方請(qǐng)指正。

記錄于 2020年6月19號(hào)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容