Android technical knowledge point: how to use data binding to eliminate findViewById()

 Encounter problems

Every time you use the findViewById() function to obtain a reference to a view after it is created or recreated, the Android system traverses the view hierarchy to find it at runtime. This is not a problem when your app has only a few views. However, a production application may have dozens of views in a layout, and even with the best designs, there will be nested views.

Consider a linear layout containing a scroll view that contains a text view. For larger or deeper view hierarchies, finding the view may take sufficient time, significantly slowing down the user's application. Caching views in variables helps, but you still have to initialize a variable for each view in each namespace. With many Views and multiple Activities, these add up, which leads to increased duplication of code and reduced project maintainability, a technical pain point for all developers.

Technical solutions

Create an object containing a reference to each view. This object, called the Binding object, can be used by your entire application. This technique is called "data binding". After you create a binding object for your app, you can access views and other data through the binding object without having to traverse the view hierarchy or search for data.

Data binding has the following benefits:

  • The code is shorter, easier to read and maintain than the code using findViewById().
  • Data and views are clearly separated.
  • The Android system only needs to traverse the view hierarchy once to get each view, which happens during application startup, not at runtime when the user is interacting with the application.
  • You get type safety for accessing views. (Type safety means that the compiler validates the type at compile time and throws an error if you try to assign the wrong type to a variable.)

In this task, you will set up data binding and use data binding to replace calls to findViewById() with calls to the bound object.

Steps

Step 1: Enable data binding

To use data binding, you need to enable data binding in your Gradle file as it is not enabled by default. This is because data binding increases compilation time and can affect application startup time.

1. Open the build.gradle (Module: project name.app) file, as shown in the following figure:

2.添加一个「buildFeatures」大括号并设置dataBinding为true,代码如下:

android {
  ...
  
  buildFeatures {
    dataBinding true
  }
}

3.出现同步项目的提示时,点击「立刻同步(Sync Now)」,如果没有提示,请依次执行「文件(File)> 使用Gradle文件来同步项目(Sync Project with Gradle Files)」操作,或直接点击工具栏右侧的Gradle图标,如下图所示:

第 2 步:更改布局文件以用于数据绑定 

要使用数据绑定,您需要使用标签来包装XML 布局。这样根类就不再是视图组,而是包含视图组和视图的布局。然后绑定对象可以识别出布局和其中的视图。

1.打开activity_main.xml文件,并切换到「代码(Code)」选项卡,如下图所示:

2.将之前的ConstraintLayout标签替换为标签。

通常的语法结构,代码如下:

<layout>
   <LinearLayout ... >
   ...
   </LinearLayout>
</layout>

示例代码,​如下:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center">

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/btnText" />

    </LinearLayout>

</layout>

「小知识」

依次执行「代码(Code) > 重新格式化代码(Reformat Code)」操作,修复代码缩进即可,如下图所示:

第 3 步:在MainActivity类中创建绑定对象 

将绑定对象的引用添加到MainActivity类内,以便您可以使用它来访问视图。

1.打开MainActivity.kt或MainActivity.java文件,代码如下:

Kotlin

import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

}

Java

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

2.在onCreate()方法上为绑定对象创建一个变量。该变量通常称为binding。binding类型,ActivityMainBinding类是由编译器专门为此主活动创建的。该名称来自布局文件的名称,即activity_main+Binding。

流程思路,如下图所示:

「小知识」

小驼峰式命名法(lower camel case):第一个单字以小写字母开始,第二个单字的首字母大写。例如:firstName、lastName。
大驼峰式命名法(upper camel case):每一个单字的首字母都采用大写字母,例如:FirstName、LastName、CamelCase。

示例代码,如下:

// Kotlin
private lateinit var binding: ActivityMainBinding

// Java
ActivityMainBinding binding;

3.点击ActivityMainBinding,并按下「Alt+Enter(Win版)或Option+Enter(Mac版)」组合键,导入这个缺失的类即可。

导入前,提示「导入ActivityMainBinding」,如下图所示:

 Kotlin

Java

导入后,添加相关的import语句,代码如下:

// Kotlin
import com.fm.test.databinding.ActivityMainBinding

// Java
import com.fm.test.databinding.ActivityMainBinding;

4.使用来自DataBindingUtil类的setContentView()函数来与带有MainActivity类的activity_main布局相关联。此setContentView()函数还负责视图的一些数据绑定设置。在onCreate()中,用以下代码行替换之前的setContentView()函数调用。

替换前

//Kotlin
setContentView(R.layout.activity_main)

//Java
setContentView(R.layout.activity_main);

替换后

//Kotlin
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

//Java
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

5.导入DataBindingUtil类,代码如下:

//Kotlin
import androidx.databinding.DataBindingUtil

//Java
import androidx.databinding.DataBindingUtil;

第 4 步:使用绑定对象替换对findViewById()的所有调用

现在可以将对绑定对象中视图的引用替换为对findViewById()的所有调用。创建绑定对象时,编译器从从布局中视图的ID生成绑定对象中视图的名称。例如,按钮的id属性值是user_btn,和绑定对象中的userBtn一样。

在onCreate()中,将findViewById()替换为引用绑定对象中的ID属性值「注意:以小驼峰式命名法(lower camel case)为准」。将findViewById(R.id.btn)替换为binding.btn,并添加要执行的操作代码,代码如下:

Kotlin

import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.fm.test.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        binding.btn.setOnClickListener(this::clickHandlerFunction)
    }

     private fun clickHandlerFunction(view: View) {
       Toast.makeText(this,"我是未来码匠",Toast.LENGTH_LONG).show()
    }

}

Java

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import com.fm.test.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {

    ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
        binding.btn.setOnClickListener(this::clickHandlerFunction);
    }

    public void clickHandlerFunction(View view) {
        Toast.makeText(this,"我是未来码匠", Toast.LENGTH_LONG).show();
    }
}

提示

If you see compiler errors after making changes, choose Build > Clean Project, then choose Build > Rebuild Project. Doing so will usually update the generated files. Otherwise, choose File > Invalidate Caches/Restart for a more thorough cleanup.

You learned earlier about the Resources object that holds references to all resources in your application. You can Binding objects in a similar way when referencing a view; however, the Binding object is much more complex.

running result

Summarize

Steps to replace the call to findViewById() with data binding:

  1. Enable data binding inside the android section of the build.gradle (Module: projectname.app) file: buildFeatures { dataBinding true }
  2. Used as the root view in XML layouts.
  3. Define binding variables: private lateinit var binding:ActivityMainBinding (Kotlin) or ActivityMainBinding binding
  4. Create a binding object inside the MainActivity class and replace setContentView(R.layout.activity_main) with binding = DataBindingUtil.setContentView(this, R.layout.activity_main).
  5. Replace the call to findViewById() with a reference to the value of the view ID property in the binding object. For example: findViewById
(R.id.btn)=>binding.btn, that is, in this example, the view name is the view ID attribute value in the XML file "Note: lower camel case prevails".

Practice gives true knowledge, and research gives wisdom. No matter how difficult it is, no matter how hard it is, keep a wise and courageous heart, study carefully, analyze problems, think carefully, find and seize breakthroughs, and then solve problems only when the time comes. To overcome difficulties, you must have patience, otherwise you will not be able to challenge yourself and break through the limits.

到这里为止,欢迎大神们随便吐槽我所写的技术文章,抓住我的痛点,请献上最宝贵的最佳的技术方案吧。放心吧,我不会复仇大家,因为大家永远都是我最好的导师。若大家对此有疑惑的地方,就能找我讨论一下,开阔眼界,增长见识。我希望得到大家的鼓励和点赞,将是我创作的最大动力。

作者声明

本篇经验系本人依照真实经历原创,需要转载到博客、自媒体平台、技术网站等,未经许可,严格遵守本人的知识版权,谢绝转载。如想转载,请联系本人授权。

联系邮箱:[email protected]

微信号:X9267543839

QQ:3403978592

Guess you like

Origin juejin.im/post/7122379358064345101