原由
ViewBinding是Google發佈的一個View綁定框架,目的是為了要讓開發者用更簡單的方式取代findViewById。
由於我現在已經完全採用Kotlin來開發Android APP了,加上Kotlin有提供Kotlin Android Extensions的gradle外掛。
因此我也兩三年沒用findViewById了。
那為什麼我會開始使用ViewBinding?
主要是因為前陣子在build程式碼的時候,發現console視窗有一行提示訊息:
The 'kotlin-android-extensions' Gradle plugin is deprecated. Please use this migration guide (https://goo.gle/kotlin-android-extensions-deprecation) to start working with View Binding (https://developer.android.com/topic/libraries/view-binding) and the 'kotlin-parcelize' plugin.
雖然不知道何年何月才會正式棄用,加上做的案子越來越多。如果突然宣布正式棄用,估計我會改到沒日沒夜吧⋯⋯
於是趁還沒棄用前,趕緊將程式碼轉移到ViewBinding框架上。
導入ViewBinding
由於ViewBinding必須要在Android Studio 3.6或者更高的版本才能執行,因此必須將Android Studio更新到3.6或是更新的版本。
1.打開Android Studio專案,在app層級的build.gradle中開啟viewBinding功能,如下所示:
android {
...以下省略
viewBinding.enabled = true
}
2.接著改寫Activity中的setContentView()程式碼,如下所示:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
}
}
第3行的ActivityMainBinding類別是IDE自動幫你生成的,對應的是activity_main.xml這個layout文件。
第6~7行的作用是在onCreate()時,將畫面新增到Activity中。
3.要使用UI元件時,直接透過binding.<UI元件名稱>即可,如下所示:
binding.button.setOnClickListener {
binding.textView.text = "You press a button"
}
進階用法
BaseActivity
在開發APP時,為了減少許多重複性的程式碼(跳出AlertDialog、顯示/隱藏虛擬鍵盤等)。
將重複的程式碼封裝成一個BaseActivity是再正常不過的事情了,那麼基於ViewBinding的BaseActivity要怎麼寫呢?
我們可以將ViewBinding類別的用泛型傳入,如下所示:
abstract class BaseActivity<T : ViewBinding>: AppCompatActivity(){
private lateinit var _binding: T
protected val binding get() = _binding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = getViewBinding()
setContentView(_binding.root)
}
protected abstract fun getViewBinding(): T
}
之後在Activity中繼承BaseActivity,並將layout文件的Binding類別傳入即可,如下所示:
class MainActivity : BaseActivity<ActivityMainBinding>() {
override fun getViewBinding() = ActivityMainBinding.inflate(layoutInflater)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
}