Android, findViewById, ViewBinding, DataBinding


Android, findViewById, ViewBinding, DataBinding

在 Android 早期我們為了取得畫面中的元件 我們一定都用過 findViewById 並對他是又愛又恨

在經歷過各種花式 NullPointerException 之後投靠像是 Butter Knife 的懷抱

而隨著 Android jetpack 相關工具陸續出籠 Butter Knife 也被 ViewBinding 取代

相信 有點年紀的 Android 工程師都對以下程式碼不陌生

TextView tvTitle = (TextView) getView().findViewById(R.id.tv_title);
TextView tvUserName = (TextView) getView().findViewById(R.id.tv_user_name);
TextView tvUserAge = (TextView) getView().findViewById(R.id.tv_user_age);
Button btnLogout = (TextView) getView().findViewById(R.id.btn_logout);

那上面只是舉例 通常我們的 Activity 這種程式碼短則數行多則數十行都有 有時不小心型別打錯就噴出各種花式 Exception 好在現在我們有 ViewBinding

ViewBinding

假設我們現在有個 xml 畫面如下 那我們怎麼使用呢 其實也只要兩個步驟

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:textColor="@color/black"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Steps 1: 在 app 的 build.gradle 的 android 下中新增

android {
    ...
    buildFeatures {
        viewBinding true
    }
}

Steps 2: Activity 中這樣使用

class MainActivity : Activity() {
    private lateinit var mBinding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(mBinding.root)
        mBinding.tvTitle.text = "Hello ViewBinding"
    }
}

這樣就完成啦~~

有人會有疑問 ActivityMainBinding 是哪來的?

是根據你的 xml 檔名 如果你的檔名叫做 activity_main.xml 那就會產生 ActivityMainBinding

那如果沒看到他 可以使用工具列的 Build > Mark Project 來產生

在 Fragment 中可以這麼使用

class MainFragment : Fragment() {

    private lateinit var mBinding: FragmentMainBinding

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        mBinding = FragmentMainBinding.inflate(layoutInflater, container, false)
        return mBinding.root
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        mBinding.tvTitle.text = "Hello ViewBinding"
    }
}

在 RecyclerView 的 Adapter 也可以使用

//僅寫出產生 view binding 的部分
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    return ViewHolder(
        AdapterBinding.inflate(LayoutInflater.from(parent.context), parent, false)
    )
}
//...

自此我們就可以與 findViewById 說 ByeBye 啦

Kotlin Android Extensions

那如果你是直接從 Kotlin 開始學習 Android 的

你應該在剛開始學習的時候 會發現你可以直接取用 view 而不用 findViewById 或是 ViewBinding

那是因為 在你使用的同時 會自動 import kotlinx.android.synthetic.<layout>.*

簡單說明一下 Kotlin Android Extensions 是創造 Kotlin 語言的團隊 JetBrains 所做的 plugin 在 jetpack 有 ViewBinding 之後該團隊也將 Kotlin Android Extensions 棄用

既然被棄用了那他跟 ViewBinding 的優缺點就不再比較 反正不是親生的

DataBinding

DataBinding 跟 ViewBinding 最大的不同就是 DataBinding 可以雙向連結

意思就是當 model 改變時 UI 可以同步更新,而 UI 改變 model 也同步更新

可以把 DataBinding 看作是 ViewBinding 的進階版

因為 ViewBinding 做得到的 DataBinding 都做得到

至於怎麼使用 就再說摟


WRITTEN BY
Aki

熱愛寫code的開發者,專注於 Android 手機 Native App 開發,對於 IOS 也有涉略。閒暇之餘也學習 JavaScript 等前端框架