Thema
- Trình diện ứng dụng bao gồm ba trường Nhập liệu và một Nhãn Text.
- Yêu cầu: Nhãn Text hiển thị tổng của ba trường Nhập liệu một cách thời gian thực.
- Nếu dữ liệu nhập không phải là số, coi giá trị đó là 0.
- Giá trị ban đầu của ba trường Nhập liệu lần lượt là 1, 2, 3.
Tạo mới dự án
Mở Android Studio và tạo mới dự án qua File / New / Project...
Trong trang hướng dẫn tạo dự án đầu tiên, điền tên ứng dụng là RxExample và tích chọn Include Kotlin support.
Trên trang hướng dẫn thứ tư, nhấn nút Finish để tạo dự án.
Cập nhật build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 28
buildToolsVersion '28.0.2'
defaultConfig {
applicationId "com.zwstudio.rxexample"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:appcompat-v7:28.0.0-rc01'
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
implementation 'io.reactivex.rxjava2:rxjava:2.1.16'
implementation 'io.reactivex.rxjava2:rxkotlin:2.2.0'
implementation 'com.jakewharton.rxbinding2:rxbinding-kotlin:2.1.1'
}
Cấu hình giao diện người dùng
Mở file activity_main.xml và thay thế phần TextView mặc định bằng cấu trúc GridLayout sau:
<GridLayout
android:layout_width="120dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:rowCount="5"
android:columnCount="2">
<EditText
android:id="@+id/edtSo1"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="end"
android:layout_row="0"
android:layout_column="1"
android:inputType="number"
android:hint="0"
android:text="1" />
<EditText
android:id="@+id/edtSo2"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="end"
android:layout_row="1"
android:layout_column="1"
android:inputType="number"
android:hint="0"
android:text="2" />
<TextView
android:id="@+id/tvCong"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_row="2"
android:layout_column="0"
android:gravity="end"
android:text="+"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
<EditText
android:id="@+id/edtSo3"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_row="2"
android:layout_column="1"
android:gravity="end"
android:inputType="number"
android:hint="0"
android:text="3" />
<TextView
android:id="@+id/tvKetQua"
android:layout_row="3"
android:layout_column="1"
android:layout_width="76dp"
android:gravity="end"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:text="16" />
</GridLayout>
Biến kiểm soát
val edtSo1 = findViewById<EditText>(R.id.edtSo1)
val edtSo2 = findViewById<EditText>(R.id.edtSo2)
val edtSo3 = findViewById<EditText>(R.id.edtSo3)
val tvKetQua = findViewById<TextView>(R.id.tvKetQua)
Giải pháp truyền thống không sử dụng RxJava
val theoDoiText = object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
val so1 = edtSo1.text.toString().toIntOrNull() ?: 0
val so2 = edtSo2.text.toString().toIntOrNull() ?: 0
val so3 = edtSo3.text.toString().toIntOrNull() ?: 0
tvKetQua.text = (so1 + so2 + so3).toString()
}
}
edtSo1.addTextChangedListener(theoDoiText)
edtSo2.addTextChangedListener(theoDoiText)
edtSo3.addTextChangedListener(theoDoiText)
edtSo1.text = edtSo1.text
Giải pháp sử dụng RxJava
Observable.combineLatest(
RxTextView.textChanges(edtSo1),
RxTextView.textChanges(edtSo2),
RxTextView.textChanges(edtSo3)
) { nhan1, nhan2, nhan3 ->
val so1 = nhan1.toString().toIntOrNull() ?: 0
val so2 = nhan2.toString().toIntOrNull() ?: 0
val so3 = nhan3.toString().toIntOrNull() ?: 0
(so1 + so2 + so3).toString()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(RxTextView.text(tvKetQua))