Android Jetpack ViewBinding

ViewBinding(視圖綁定)
通過ViewBinding,可以更輕松地編寫可與視圖交互的代碼。在模塊中啟用ViewBinding后,系統(tǒng)會(huì)為該模塊中的每個(gè)XML布局文件生成一個(gè)綁定類。綁定類的實(shí)例包含對(duì)在相應(yīng)布局中具有ID的所有視圖的直接引用。多數(shù)情況下ViewBinding會(huì)替換掉findViewById。開啟方式有如下兩種方式:

    //方式一  
    viewBinding{
      enabled=true
    }
    //方式二 
    buildFeatures {
        viewBinding true
    }

如果希望在生成綁定類的時(shí)候忽略某個(gè)布局文件,可以在布局文件的根目錄上添加tools:viewBindingIgnore="true"屬性。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:viewBindingIgnore="true">

</LinearLayout>

模塊開啟視圖綁定功能后,系統(tǒng)會(huì)為該模塊中包含的每個(gè)XML布局文件生成一個(gè)綁定類。每個(gè)綁定類均包含對(duì)根View以及布局中具有ID的所有視圖的引用。系統(tǒng)生成綁定類的命名方式是:通過將XML文件的名稱去下劃線后轉(zhuǎn)換成駝峰式大小寫并在末尾添加"Binding"的方式。例如 activity_main.xml 會(huì)生成一個(gè)ActivityMainBinding的視圖綁定類。如下為activity_main.xml文件的內(nèi)容

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/name_view"
        android:layout_width="match_parent"
        android:layout_height="46dp"
        android:gravity="center"
        android:text="@string/app_name" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="46dp"
        android:gravity="center"
        android:text="ceshi" />

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="46dp"
        android:text="確定" />
</LinearLayout>

此XML布局文件對(duì)應(yīng)的ActivityMainBinding類,包含了對(duì)根視圖的引用及具有ID 的View的引用,通過綁定類 具體實(shí)例的getRoot()方法來獲取根視圖的引用,視圖中具有ID的view則會(huì)在綁定類中生成相應(yīng)ID名稱對(duì)應(yīng)的字段,如此視圖中的"name_view"和"button"這兩個(gè)view會(huì)在綁定類中生成nameView 和button兩個(gè)字段(字段生成規(guī)則為去下劃線后改駝峰式大小寫命名)。具體生成的綁定類如下:

// Generated by view binder compiler. Do not edit!
package com.gexing.test.databinding;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.viewbinding.ViewBinding;
import com.gexing.test.R;
import java.lang.NullPointerException;
import java.lang.Override;
import java.lang.String;

public final class ActivityMainBinding implements ViewBinding {
  @NonNull
  private final LinearLayout rootView;

  @NonNull
  public final Button button;

  @NonNull
  public final TextView nameView;

  private ActivityMainBinding(@NonNull LinearLayout rootView, @NonNull Button button,
      @NonNull TextView nameView) {
    this.rootView = rootView;
    this.button = button;
    this.nameView = nameView;
  }

  @Override
  @NonNull
  public LinearLayout getRoot() {
    return rootView;
  }

  @NonNull
  public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater) {
    return inflate(inflater, null, false);
  }

  @NonNull
  public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater,
      @Nullable ViewGroup parent, boolean attachToParent) {
    View root = inflater.inflate(R.layout.activity_main, parent, false);
    if (attachToParent) {
      parent.addView(root);
    }
    return bind(root);
  }

  @NonNull
  public static ActivityMainBinding bind(@NonNull View rootView) {
    // The body of this method is generated in a way you would not otherwise write.
    // This is done to optimize the compiled bytecode for size and performance.
    int id;
    missingId: {
      id = R.id.button;
      Button button = rootView.findViewById(id);
      if (button == null) {
        break missingId;
      }

      id = R.id.name_view;
      TextView nameView = rootView.findViewById(id);
      if (nameView == null) {
        break missingId;
      }

      return new ActivityMainBinding((LinearLayout) rootView, button, nameView);
    }
    String missingId = rootView.getResources().getResourceName(id);
    throw new NullPointerException("Missing required view with ID: ".concat(missingId));
  }
}

ViewBinding如何在Activity和Fragment中使用:
上述綁定類中 我們發(fā)現(xiàn)有多個(gè)靜態(tài)類方法:

1.ActivityMainBinding inflate(@NonNull LayoutInflater inflater)
2.public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater,
@Nullable ViewGroup parent, boolean attachToParent)
3.public static ActivityMainBinding bind(@NonNull View rootView)
這三個(gè)靜態(tài)方法的返回值都式綁定類類型的實(shí)例,通過這個(gè)實(shí)例我們便可以獲取到相應(yīng)的rootView 由此便可以在activity和fragment中使用。

在Activity中使用:直接在onCreate方法中替換原有的setContentView(R.layout.activity_main)的方式

package com.gexing.test

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.gexing.test.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    lateinit var mainBinding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
//        setContentView(R.layout.activity_main)
        mainBinding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(mainBinding.root)
    }
}

在Fragment中使用:在onCreateView方法中處理

package com.gexing.test

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.gexing.test.databinding.ActivityMainBinding

class TestFragment : Fragment() {
    var mainBinding: ActivityMainBinding? = null
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        mainBinding = mainBinding ?: ActivityMainBinding.inflate(inflater, container, false)
        return mainBinding?.root
    }
}
override fun onDestroyView() {
        super.onDestroyView()
        mainBinding = null
    }

ViewBinding與普通findViewById的區(qū)別:

1.Null安全,由于ViewBinding會(huì)創(chuàng)建對(duì)視圖的直接引用,因此不存在因視圖ID無效而引發(fā)的Null指針異常的風(fēng)險(xiǎn)。此外如果視圖僅出現(xiàn)在布局的某些配置中,則綁定類中包含其引用的字段會(huì)使用@Nullable標(biāo)記。
2.類型安全每個(gè)綁定類中的字段均具有與它們XML文件中引用的View相匹配的類型,這意味著不存在類轉(zhuǎn)換異常的風(fēng)險(xiǎn)。
這些差異意味著布局和代碼之間的不兼容將會(huì)導(dǎo)致構(gòu)建在編譯時(shí)失敗,而非在運(yùn)行時(shí)出現(xiàn)異常。

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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