在Android开发中,在代码中获取Activity中定义的控件和为控件绑定响应事件是件繁琐而无趣的事情,特别是在企业应用中,通常在一个界面(Activity)中会有大量的收入项,需要反复调用findViewById和setOnClickListener这样的函数。
下面的代码是一个简单的登录界面,包含用户名、密码两个输入框输入框和一个登录按钮。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class MainActivity extends AppCompatActivity { private static final String TAG = "[" + MainActivity.class.getSimpleName() +"]"; private EditText txtUserId; private EditText txtPwd; private Button btnLogin; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); txtUserId = (EditText)findViewById(R.id.txtUserId); txtPwd = (EditText)findViewById(R.id.txtPwd); btnLogin = (Button)findViewById(R.id.btnLogin); btnLogin.setOnClickListener(v -> { Log.d(TAG, "Login clicked. userId = " + txtUserId.getText().toString()); }); } }
使用butterknife库 要在 Android 项目中使用 butterknife 库,需要对项目完成两步设置:
在 build.gradle(Module:app) 文件中增加依赖项: 1 2 3 4 5 dependencies { implementation 'com.jakewharton:butterknife:10.1.0' annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0' }
并将Java的版本设置为1.8
1 2 3 4 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 }
修改后完整的 build.gradle(Module:app) 文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 apply plugin: 'com.android.application' android { compileSdkVersion 29 buildToolsVersion "29.0.1" defaultConfig { applicationId "cn.com.hohistar.tutorial.basicwidgettutorial" minSdkVersion 15 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 fileTree(dir: 'libs' , include: ['*.jar' ]) implementation 'androidx.appcompat:appcompat:1.0.2' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' implementation 'com.jakewharton:butterknife:10.1.0' annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0' }
在 build.gradle(Project: xxxx) 文件中增加: (替换 xxxx 为你的项目名) 1 classpath 'com.jakewharton:butterknife-gradle-plugin:10.0.0'
修改后完整的 build.gradle(Project: xxxx) 文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.4.2' classpath 'com.jakewharton:butterknife-gradle-plugin:10.0.0' } } allprojects { repositories { google() jcenter() } } task clean(type: Delete) { delete rootProject.buildDir }
初始化 butterknife 在每个想要使用 butterknife 功能的 Activity ,都必须要进行一次初始化。通常这个工作是放在 Activity 的 onCreate 方法中来完成, 代码如下:
1 2 3 4 5 6 7 @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this ); }
代码中第6行就是调用 ButterKnife 的 bind 静态函数进行初始。注意: 对于每个 Activity 都一定要执行这行代码进行初始化,否则会出现注解(绑定)既不生效,也不报错的情况。
绑定按钮单击事件 在前面的例子中,为了绑定按钮的单价事件,我们需要首先获取按钮的实例(findViewById),然后调用setOnClickLister方法进行绑定。使用 ButterKnife 后,我们只需要使用 @OnClick 注解就可以完成绑定。下面对比一下代码:
旧的代码
1 2 3 4 5 btnLogin = (Button)findViewById(R.id.btnLogin); btnLogin.setOnClickListener(v -> { Log.d(TAG, "Login clicked. userId = " + txtUserId.getText().toString()); });
新的代码
1 2 3 @OnClick (R.id.btnLogin) void onLogin () { Log.d(TAG, "Login clicked. userId = " + txtUserId.getText().toString()); }
可以看到,新的代码中,直接通过 @OnClick 注解的参数指明需要绑定的对象,简介很多。
修改后完整的 Activity 代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class MainActivity extends AppCompatActivity { private static final String TAG = "[" + MainActivity.class.getSimpleName() +"]"; private EditText txtUserId; private EditText txtPwd; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); txtUserId = (EditText)findViewById(R.id.txtUserId); txtPwd = (EditText)findViewById(R.id.txtPwd); } @OnClick (R.id.btnLogin) void onLogin () { Log.d(TAG, "Login clicked. userId = " + txtUserId.getText().toString()); } }
绑定屏幕上的控件 在原来的程序中,当在程序中需要获取输入框的值时,我们需要首先用 findViewById 取得控件的实例,在进行操作:
1 2 3 4 5 6 7 8 9 10 private EditText txtUserId;private EditText txtPwd;txtUserId = (EditText)findViewById(R.id.txtUserId); txtPwd = (EditText)findViewById(R.id.txtPwd); Log.d(TAG, "Login clicked. userId = " + txtUserId.getText().toString());
使用 ButterKnife, 用 @BindView 直接进行绑定,这样代码就会更简洁些:
1 2 3 4 5 6 @BindView (R.id.txtUserId) EditText txtUserId;@BindView (R.id.txtPwd) EditText txtPwd;Log.d(TAG, "Login clicked. userId = " + txtUserId.getText().toString());
可以看到,操作数据的代码没变,但省了获取实例的代码。