By default, the reader of this article has some Android development experience and a brief understanding of the Android Annotations and DataBinding technology.
The article concludes with a summary of why DataBinding’s technology should be used by comparing the code in three different ways.
function
The function of the three different codes is to dynamically control the click status of the login button on the login interface by monitoring the text changes in the user name and password input boxes.
The first is a generic implementation
If you write code in the normal way, you can find a lot of redundancy, most of which is repetitive work:
- Instantiate view:
findViewById(...)
- Add text listener:
addTextChangedListener(...)
- Set click events:
setOnClickListener(...)
The XML file has two EditTexts and a Button. This is a simple one, so instead of Posting the code here, just post the Activity code:
public class LoginNormalActivity extends AppCompatActivity {
private EditText nameEdit;
private EditText pwdEdit;
private Button loginBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); .// Instantiate view
nameEdit = (EditText) findViewById(R.id.login_name_edit);
pwdEdit = (EditText) findViewById(R.id.login_pwd_edit);
loginBtn = (Button) findViewById(R.id.login_btn);
// Add text change listener
OnTextChangeListener textChangeListener = new OnTextChangeListener();
nameEdit.addTextChangedListener(textChangeListener);
pwdEdit.addTextChangedListener(textChangeListener);
// Login button click event listener
loginBtn.setOnClickListener(v -> Toast.makeText(this."click login!", Toast.LENGTH_SHORT).show());
updateLoginEnable();
}
/** * Updates the status of the login button */
private void updateLoginEnable(a) { loginBtn.setEnabled(! (TextUtils.isEmpty(nameEdit.getText()) || TextUtils.isEmpty(pwdEdit.getText()))); }/** * Text changes Listener */
private class OnTextChangeListener implements TextWatcher {...@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Update the text after it has changedupdateLoginEnable(); }}}Copy the code
The second type: Android Annotations
Writing code with annotations allows you to focus on what’s really important and makes code simpler:
- Through annotation
@ViewById
@Click
@AfterTextChange
Solve a lot of repetitive tasks - APT generates a new class at compile time, the naming rule is the original class name underlined, no reflection, will not affect the efficiency of the program to run, but the new compiled class will increase your awareness, use a little uncomfortable.
The XML file has two EditTexts and a Button, which is quite simple. Again, we don’t post any code, just post the Activity code:
@EActivity(R.layout.login_activity)
public class LoginAnnotationActivity extends AppCompatActivity {
// Instantiate view
@ViewById(R.id.login_name_edit)
protected EditText nameEdit;
@ViewById(R.id.login_pwd_edit)
protected EditText pwdEdit;
@ViewById(R.id.login_btn)
protected Button loginBtn;
@AfterViews
protected void initView(a) {
updateLoginEnable();
}
/** * Updates the status of the login button */
private void updateLoginEnable(a) { loginBtn.setEnabled(! (TextUtils.isEmpty(nameEdit.getText()) || TextUtils.isEmpty(pwdEdit.getText()))); }/** * Login click callback */
@Click(R.id.login_btn)
protected void login(View view) {
Toast.makeText(this."click login!", Toast.LENGTH_SHORT).show();
}
// Add text change listener
@AfterTextChange({R.id.login_pwd_edit, R.id.login_name_edit})
protected void afterTextChange(TextView tv, Editable text) {
// Update the text after it has changedupdateLoginEnable(); }}Copy the code
Third: DataBinding implementation
Binding mode: The data and UI layers are decoupled based on the removal of redundant code
- through
android:text="@={... }"
Bind data bidirectionally to the UI - through
android:enabled="@{... }"
Control button status - through
android:onClick="@{... }"
Handle user action events directly - Generate auxiliary tool classes with APT during compilation to achieve dynamic binding of data and UI
First, the XML file code:
<?xml version="1.0" encoding="utf-8"? >
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="loginViewHelper"
type="com.free.fastmvpdemo.login.LoginViewHelper" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="20dp"
android:paddingRight="20dp">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:hint="@string/account_hint"
android:text="@={loginViewHelper.name}" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:hint="@string/pwd_hint"
android:text="@={loginViewHelper.pwd}" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="@{loginViewHelper.canLogin(loginViewHelper.name,loginViewHelper.pwd)}"
android:onClick="@{loginViewHelper.login}"
android:text="@string/login" />
</LinearLayout>
</layout>Copy the code
As shown in the XML code, the data binding rules are already in place. In fact, the Java code only needs to handle the business related logic, which is very clear.
public class LoginActivity extends AppCompatActivity {
//DataBinding automatically generates classes that take XML file names and end with Binding
LoginActivityBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {...// Initialize data bind and set the Helper instance
binding = DataBindingUtil.setContentView(this, R.layout.login_activity);
binding.setLoginViewHelper(newLoginViewHelper()); }}public class LoginViewHelper {
// Listen for attributes
public ObservableField<String> name = new ObservableField<>();
public ObservableField<String> pwd = new ObservableField<>();
/** * Login click callback */
public void login(View view) {
Toast.makeText(view.getContext(), "click login!", Toast.LENGTH_SHORT).show();
}
/** * Whether to log in */
public boolean canLogin(String name, String pwd) {
return !(TextUtils.isEmpty(name) || TextUtils.isEmpty(pwd));
}
}Copy the code
conclusion
- Common approach: Too much redundant code, so we should abandon common approach and embrace new technology
- Annotation method: through annotation to solve the vast majority of repetitive work, and no reflection, does not affect the efficiency of the program, just need to recognize some classes, use a little uncomfortable. However, in some Activity jump broadcast receivers, annotations have a natural advantage in making your code clearer.
- Binding mode: Data-driven: Automatically updates the UI after data changes; Event handling: Directly find the target instance to handle the event of the user’s action. This way we don’t need to deal with the UI or controls, we just need to handle the business logic in Java code, very clear, and leave the rest to the Binding library. This reduces code coupling and makes data independent of the UI, which has a positive impact on future program changes and maintenance. Think long term about the preferred binding method.
One final note: Android bindings are still a bit behind the angularJS front end, especially when it comes to bidirectional binding, and Android Studio’s support for DataBinding error reporting and automatic code generation is not very friendly. Of course, this is just the status quo, and it will get better.