从一个简单的安卓应用了解View Binding

从一个简单的安卓应用了解View Binding

视图绑定,越来越像Web开发了......

上一篇文章提的那本书,源代码可以从这里下载,只需要简单注册一下即可.

然后按照书里第三章创建了一个非常简单的输入美元,然后按照0.85的汇率转换成欧元的应用.

所做的事情其实和Web开发很类似,先有一个Activity也就是页面,然后给这个页面添加一个输入框,一个显示文本的框,和一个按钮. 然后编写这个页面对应的Java类,添加一个方法或者说事件处理器,在按钮按下的时候触发事件,从输入框中读取金额,然后进行计算,再渲染到文本框中.

获取资源的两种方式

根据ID查找视图(页面组件)

在之前已经知道,所有的资源可以通过R类来访问,看一下这个简单项目中的代码:

EditText dollarText = findViewById(R.id.dollarText);
TextView textView = findViewById(R.id.textView);

这个R.id.后边的部分,就是视图的id名称,通过这个方法,可以直接获取视图,然后就可以更改样式或者内容,类似于WEB开发中获取HTML元素.

Android Studio 3.6之前,想要获取元素,唯一的办法就是像上边的代码一样使用findViewById()方法(有AppCompatActivity类提供).

这个方法比较准确方便,如果是有不便之处的话,就是还不能引用尚未创建的元素,否则会报空指针错误.

视图绑定 View Bindings

AS 3.6之后,如果设置了启用视图绑定,AS会自动为每一个layout布局文件(layout目录下的XML文件)创建一个绑定类,这个绑定类根据布局文件的名称,改成驼峰之后加上Binding来命名,比如activity_main.xml的绑定类就是ActivityMainBinding.这样通过类名就可以来访问视图资源,现在就来看一下如何将原来的代码改造成使用视图绑定.

改造原来的代码

启用视图绑定

默认情况下,视图绑定功能没有启用.如果要启用的话,必须对模块(Module)级别的build.gradle文件进行修改.在左侧的1.Project窗口最下边的Gradle Scripts中, 找到build.gradle(Module:XXXX.app),双击打开,文件中的内容如下:

plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 29
    buildToolsVersion "30.0.2"

    defaultConfig {
        applicationId "com.ebookfrenzy.androidsample"
        minSdkVersion 26
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

在其中的android部分中,增加如下配置:

android {
    ......
    buildFeatures {
        viewBinding = true
    }
    ......

我这里配置好之后,重新同步,gradle会去下载视图绑定所需要的文件.之后需要重新编译,在右侧Gradle菜单中选择Tasks-build-build即可.

改造代码

先来看一下原始的代码:

package com.ebookfrenzy.androidsample;

import androidx.appcompat.app.AppCompatActivity;

import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

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

    public void convertCurrency(View view) {

        EditText dollarText = findViewById(R.id.dollarText);
        TextView textView = findViewById(R.id.textView);

        if (!dollarText.getText().toString().equals("")) {

            float dollarValue = Float.valueOf(dollarText.getText().toString());
            Float euroValue = dollarValue * 0.85F;
            textView.setText(euroValue.toString());
        } else {
            textView.setText(R.string.no_value_string);
        }
    }
}

接下来开始改造.

添加视图绑定类的引用

由于我们知道了绑定类的类名应该是ActivityMainBinding,先给当前类添加一个域:

public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding binding;
}

启用了视图绑定之后,AS可以自动提示补完这个类,说明已经认出来了.

删除那些R类的代码并替换成绑定类"进入"的代码

这些代码在onCreate和我们自行编写的代码中都有,分别是:

setContentView(R.layout.activity_main);

EditText dollarText = findViewById(R.id.dollarText);
TextView textView = findViewById(R.id.textView);

然后一个一个来改,先是onCreate方法:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        View view = binding.getRoot();
        setContentView(view);
        
    }

这里的视图原来是直接通过R类引用,现在是从绑定类中获取View对象并进行显示.同时这里也初始化了binding对象.

然后是自己编写的业务方法:

    public void convertCurrency(View view) {

        if (!binding.dollarText.getText().toString().equals("")) {

            float dollarValue = Float.valueOf(binding.dollarText.getText().toString());
            Float euroValue = dollarValue * 0.85F;
            binding.textView.setText(euroValue.toString());
        } else {
            binding.textView.setText(R.string.no_value_string);
        }
    }

这里就是把获取View对象的方法,从原来的R类改成了bing.id的方式.

在开启视图绑定之后,原来的findViewById()依然可用,而且可以同时使用.这本书里还提到,由于代码量的关系,在代码示例中,还是使用findViewById()方法,但是在实际开发中,推荐大家使用AS的视图绑定功能.

LICENSED UNDER CC BY-NC-SA 4.0
Comment