利用ViewBinding和反射封裝的基類,從此再也不用findViewById了

今天從Google公眾號了解到關(guān)于ViewBinding的相關(guān)文章,趕上手頭項目正在做優(yōu)化欣舵,于是結(jié)合反射封裝了BaseActivity和BaseFragment,記錄下來同時和大家一起探討學(xué)習(xí)缀磕。先簡單介紹下ViewBinding:

從 Android Studio 3.6 開始缘圈,ViewBinding能夠通過生成綁定對象來替代 findViewById,從而可以幫你簡化代碼袜蚕,并且從 findViewById 的模版代碼中解脫出來糟把。ViewBinding的主要優(yōu)點是所有綁定類都是由Gradle插件生成的,因此它對構(gòu)建時間沒有影響牲剃,并且具有編譯時安全性遣疯。

ViewBinding與DataBinding的區(qū)別:

DataBinding 僅處理使用 <layout> 代碼創(chuàng)建的數(shù)據(jù)綁定布局;
ViewBinding 不支持布局變量或布局表達(dá)式凿傅,因此它不能用于在 XML 中將布局與數(shù)據(jù)綁定缠犀。

ViewBinding相較ButterKnife、Kotlin Android Extensions的幾點優(yōu)勢:

目前Android開發(fā)中完成View映射的方法主要有 findViewById狭归、 ButterKnife, 如果使用kotlin的話還可以使用Kotlin Android Extensions夭坪。

偷個懶,直接引用下其它文章中的描述:

Type safety
findViewById, ButterKnife 均存在類型轉(zhuǎn)換問題过椎,例如不小心將一個TextView錯誤的賦值給一個Button變量,都會報錯戏仓,這一錯誤很容易出現(xiàn)疚宇,關(guān)鍵在錯誤還出現(xiàn)在運行時亡鼠,而不是編譯時!
而ViewBinding中敷待,產(chǎn)生的binding類中的屬性是依據(jù)XML layout文件生成的间涵,所以類型不會錯,生成的時候已經(jīng)處理好了榜揖。
Null safety:
findViewById, ButterKnife與Kotlin Android Extensions 均存在Null不安全問題勾哩。這個什么意思呢?就是在我們訪問那個View的時候它不存在举哟。為什么會出現(xiàn)這種情況呢思劳?例如不小心使用了錯誤的Id,或者訪問的時候那個view還不存在。
使用了錯誤Id這個估計大家都有此類經(jīng)歷妨猩,但是訪問時候那個view不存在怎么理解呢潜叛?例如我們在手機橫屏和豎屏的時候分別使用一套XML layout文件,假設(shè)橫屏中包含了一個豎屏中沒有的view,那么在屏幕從橫屏旋轉(zhuǎn)到豎屏的時候壶硅,NullPointer問題就出現(xiàn)了威兜。
而ViewBinding中, 產(chǎn)生的binding類中的屬性是依據(jù)XML layout文件生成的庐椒,所以Id不會錯椒舵。而且其將僅存在某一個配置下的layout文件的那些view對應(yīng)的字段標(biāo)記為@Nullable,而且约谈,生成類中還會很貼心的給你加上詳細(xì)的注釋逮栅。這一切都是為了提醒程序員,注意對這個view特別處理窗宇,它在某些情況下為Null措伐。
簡潔優(yōu)雅
將綁定view的模板代碼自動生成到了其他類中,使controlor類(Activity军俊,F(xiàn)ragment)更加清晰了侥加。

原文鏈接:Android開發(fā)之秒懂ViewBinding,一代神器ButterKnife的終結(jié)者
————————————————

ViewBinding的常規(guī)使用:

  1. 在 build.gradle 中開啟視圖綁定
    開啟視圖綁定無須引入額外依賴,從 Android Studio 3.6 開始粪躬,視圖綁定將會內(nèi)建于 Android Gradle 插件中担败。需要打開視圖綁定的話,只需要在 build.gradle 文件中配置 viewBinding 選項:
// 需要 Android Gradle Plugin 3.6.0
android {
    viewBinding {
        enabled =true
    }
}

在 Android Studio 4.0 中镰官,viewBinding 變成屬性被整合到了 buildFeatures 選項中提前,所以配置要改成:

//Android Studio 4.0
android{
    buildFeatures{
        viewBinding=true
    }
}

配置完成后,視圖綁定就會根據(jù)現(xiàn)有的 XML 文件泳唠,為 Module 內(nèi)所有的布局文件生成綁定對象狈网。無須修改原有布局的 XML 文件,視圖綁定將根據(jù)你現(xiàn)有的布局自動完成所有工作。你可以在任何需要填充布局的地方使用綁定對象拓哺,比如 Fragment勇垛、Activity、甚至是 RecyclerView Adapter(或者說是 ViewHolder 中)士鸥。

  1. 在 Activity 中使用視圖綁定
    假如你有一個布局文件名叫 activity_my.xml闲孤,其中包含了一個按鈕和兩個文本視圖。視圖綁定會為這個布局生成一個名叫 ActivityMyBinding 的類烤礁,布局文件中所有擁有 id 的視圖讼积,都會在這個類中有一個對應(yīng)的屬性:
overridefunonCreate(savedInstanceState:Bundle?){
    super.onCreate(savedInstanceState)
    val binding = ActivityMyBinding.inflate(layoutInflater)
    binding.title.text ="Hello"
    binding.subtext.text ="World"
    binding.button.setOnClickListener {
        /* ... */
    }
    setContentView(binding.root)
}
  1. 在 Fragment,RecyclerView Adapter等的使用可參考文章:
    [譯]深入研究 ViewBinding 在 < include>, < merge>, adapter, fragment, 和 activity 中使用View Binding

————————————————

BaseActivity的封裝和使用:

abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
    lateinit var binding: VB
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //利用反射脚仔,調(diào)用指定ViewBinding中的inflate方法填充視圖
        val type = javaClass.genericSuperclass
        if (type is ParameterizedType) {
            val clazz = type.actualTypeArguments[0] as Class<VB>
            val method = clazz.getMethod("inflate", LayoutInflater::class.java)
            binding = method.invoke(null, layoutInflater) as VB
            setContentView(binding.root)
        }

        init()
    }

    abstract fun init()
}

此時勤众,我們的Activity的使用就比較簡單了:

class MyActivity : BaseActivity<ActivityMyBinding>() {
    override fun init() {
        binding.title.text ="Hello"
        binding.subtext.text ="World"
        binding.button.setOnClickListener {
            /* ... */
        }
        /* ... */
    }
}

BaseFragment的封裝和使用:

abstract class BaseFragment<VB : ViewBinding> : Fragment() {
    private var _binding : VB? = null
    val binding :VB get() = _binding!!

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        //利用反射,調(diào)用指定ViewBinding中的inflate方法填充視圖
        val type = javaClass.genericSuperclass
        val clazz = (type as ParameterizedType).actualTypeArguments[0] as Class<VB>
        val method = clazz.getMethod("inflate", LayoutInflater::class.java, ViewGroup::class.java, Boolean::class.java)
        _binding = method.invoke(null, layoutInflater, container, false) as VB
        return _binding!!.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        init()
    }

    abstract fun init()

    override fun onDestroyView() {
        _binding = null
        super.onDestroyView()
    }
}

接著在我們的Fragment使用吧玻侥!

class MyFragment : BaseFragment<FragmentMyBinding>() {
    override fun init() {
        binding.title.text ="Hello"
        binding.subtext.text ="World"
        binding.button.setOnClickListener {
            /* ... */
        }
        /* ... */
    }
}

哈哈决摧,世界清凈了!4绽肌掌桩!

本文僅作為基類封裝的參考,未考慮其它因素姑食,歡迎各位給出己見波岛,共同進(jìn)步。

寫作不易音半,如對兄弟們有幫助则拷,還望點個贊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末曹鸠,一起剝皮案震驚了整個濱河市煌茬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌彻桃,老刑警劉巖坛善,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異邻眷,居然都是意外死亡眠屎,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門肆饶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來改衩,“玉大人,你說我怎么就攤上這事驯镊『剑” “怎么了竭鞍?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長候衍。 經(jīng)常有香客問我笼蛛,道長洒放,這世上最難降的妖魔是什么蛉鹿? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮往湿,結(jié)果婚禮上妖异,老公的妹妹穿的比我還像新娘。我一直安慰自己领追,他們只是感情好他膳,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著绒窑,像睡著了一般棕孙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上些膨,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天蟀俊,我揣著相機與錄音,去河邊找鬼订雾。 笑死肢预,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的洼哎。 我是一名探鬼主播烫映,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼噩峦!你這毒婦竟也來了锭沟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤识补,失蹤者是張志新(化名)和其女友劉穎族淮,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體李请,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡瞧筛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了导盅。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片较幌。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖白翻,靈堂內(nèi)的尸體忽然破棺而出乍炉,到底是詐尸還是另有隱情绢片,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布岛琼,位于F島的核電站底循,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏槐瑞。R本人自食惡果不足惜熙涤,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望困檩。 院中可真熱鬧祠挫,春花似錦、人聲如沸悼沿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽糟趾。三九已至慌植,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間义郑,已是汗流浹背蝶柿。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留魔慷,地道東北人只锭。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像院尔,于是被迫代替她去往敵國和親蜻展。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容