---
title: "التحقق الحديث من صحة النماذج في Android باستخدام Data Binding"
description: "كيف تتحققون من صحة حقول النماذج دون تعابير if أو when"
canonical: https://oozou.com/ar/blog/modern-android-form-validations-with-data-binding-147
locale: ar
date: 2020-12-21
author: "OOZOU Team"
---

# التحقق الحديث من صحة النماذج في Android باستخدام Data Binding

> كيف تتحققون من صحة حقول النماذج دون تعابير if أو when

Published: 2020-12-21 · Author: OOZOU Team (Engineering) · 3 min read

# 
مقدمة

من الأمور الكثيرة التي يجب أن يتقنها مطوّر Android بناء النماذج (forms). ويأتي معها عبء التحقق من صحة المدخلات على جهة العميل (client side validation). هناك أساليب متنوعة لفعل ذلك، لكنني أود أن أشارككم أسلوبي المفضل.

# لنبدأ

أولًا سننشئ صنف validator يتولى التحقق من صحة قيم LiveData

```kotlin
//A predicate is a function that evaluates to true when its param matches the condition of the predicate
typealias Predicate = (value: String?) -> Boolean

class LiveDataValidator(private val liveData: LiveData<String>) {
    private val validationRules = <em>mutableListOf</em><Predicate>()
    private val errorMessages = <em>mutableListOf</em><String>()

     var error = MutableLiveData<String?>()

    <strong>//For checking if the liveData value matches the error condition set in the validation rule predicate
    //The livedata value is said to be valid when its value doesn't match an error condition set in the predicate</strong>
    fun isValid(): Boolean {
        for (i in 0 <em>until </em>validationRules.size) {
            if (validationRules[i](liveData.<em>value</em>)) {
                emitErrorMessage(errorMessages[i])
                return false
            }
        }

        emitErrorMessage(null)
        return true
    }

    <strong>//For emitting error messages</strong>
    private fun emitErrorMessage(messageRes: String?) {
        error.<em>value </em>= messageRes
    }

    <strong>//For adding validation rules</strong>
    fun addRule(errorMsg: String, predicate: Predicate) {
        validationRules.add(predicate)
        errorMessages.add(errorMsg)
    }
}
```

بعد ذلك سننشئ ValidatorResolver يساعدنا على تجميع عدة validators خاصة بـ LiveData. وسيفيدنا هذا عندما نريد التحقق من أن جميع كائنات LiveData المرتبطة بالنموذج في حالة صالحة.

```kotlin
class LiveDataValidatorResolver(private val validators: List<LiveDataValidator>) {
    fun isValid(): Boolean {
        for (validator in validators) {
            if (!validator.isValid()) return false
        }
        return true
    }
}
```

ثم سننشئ قواعد التحقق داخل الـ ViewModel

```kotlin
class ExampleViewModel : ViewModel() {
   val usernameLiveData = MutableLiveData<String>()
   val usernameValidator = LiveDataValidator(usernameLiveData).<em>apply </em><strong>{
      //Whenever the condition of the predicate is true, the error message should be emitted
      </strong>addRule("username is required") <strong>{ it</strong>.<em>isNullOrBlank</em>() <strong>}
   }
   </strong>val passwordLiveData = MutableLiveData<String>()
   val passwordValidator = LiveDataValidator(passwordLiveData).<em>apply </em><strong>{
      //We can add multiple rules. 
      //However the order in which they are added matters because the rules are checked one after the other
      </strong>addRule("password is required") <strong>{ it</strong>.<em>isNullOrBlank</em>() <strong>}
      </strong>addRule("password length must be 10") <strong>{ it?.length != 10</strong> <strong>}
   }

   //We will use a mediator so we can update the error state of our form fields
   //and the enabled state of our login button as the form data changes
   </strong>val isLoginFormValidMediator = MediatorLiveData<Boolean>()

   init {
       isLoginFormValidMediator.<em>value </em>= false
       isLoginFormValidMediator.addSource(usernameLiveData) <strong>{ </strong>validateForm() <strong>}
       </strong>isLoginFormValidMediator.addSource(passwordLiveData) <strong>{ </strong>validateForm() <strong>}</strong>
   }

   //This is called whenever the usernameLiveData and passwordLiveData changes
   fun validateForm() {
       val validators = <em>listOf</em>(usernameValidator, passwordValidator)
       val validatorResolver = LiveDataValidatorResolver(validators)
       isLoginFormValidMediator.<em>value </em>= validatorResolver.isValid()
   }
}
```

وأخيرًا سننشئ نموذج تسجيل دخول بسيطًا يحتوي على حقلين، اسم المستخدم وكلمة المرور، وزرًا لإتمام تسجيل الدخول. يفترض ملف XML التالي أنكم على دراية بـ data binding.

```
<androidx.constraintlayout.widget.ConstraintLayout
<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/field_username"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:errorEnabled="true"
    <strong>app:error="@{viewModel.usernameValidator.error}"</strong>
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <com.google.android.material.textfield.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        <strong>android:text="@={viewModel.usernameLiveData}"</strong> />

</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/field_password"
    style="@style/TextInputLayoutTheme"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:errorEnabled="true"
    <strong>app:error="@{viewModel.passwordValidator.error}"</strong>
    app:layout_constraintEnd_toEndOf="parent"
   app:layout_constraintStart_toStartOf="parent"
   app:layout_constraintTop_toBottomOf="@+id/field_username">

    <com.google.android.material.textfield.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        <strong>android:text="@={viewModel.passwordLiveData}"</strong> />

</com.google.android.material.textfield.TextInputLayout>

<com.google.android.material.button.MaterialButton
    android:id="@+id/button_log_in"
    android:layout_width="match_parent"
    android:layout_height="60dp"
     android:layout_marginTop="100dp"
    <strong>android:enabled="@{viewModel.isLoginFormValidMediator}"</strong>
    android:text="Log in"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/field_password"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<br>
```

# الخلاصة

أفضّل هذه الطريقة لأنها تجنّبني كتابة تعابير if أو when طويلة كلما كان لدي نموذج ضخم بقواعد تحقق كثيرة. وإن كنتم تحبون استعراض مهاراتكم الإبداعية، فجرّبوها في مشروعكم القادم، وفكّروا في الانضمام إلى فريقنا في Oozou.

---

Contact OOZOU: hello@oozou.com · +66 2544 0000 · https://oozou.com/ar/contact

More for AI agents: https://oozou.com/llms.txt · every page has a markdown twin at its URL plus ".md"
