I have some extension functions function below.
fun EditText.setEmailValidationListener(): TextWatcher {
val textWatcher = object : TextWatcher {
override fun beforeTextChanged(text: CharSequence?, start: Int, count: Int, after: Int) { }
override fun onTextChanged(text: CharSequence?, start: Int, before: Int, count: Int) { }
override fun afterTextChanged(text: Editable?) { validateEmail() }
private fun validateEmail(): Boolean {
if (validateEmailFormat(showError = false)) {
getParentInputLayout()?.isErrorEnabled = false
return true
}
return false
}
}
addTextChangedListener(textWatcher)
return textWatcher
}
fun EditText.setPasswordValidationListener(): TextWatcher {
val textWatcher = object : TextWatcher {
override fun beforeTextChanged(text: CharSequence?, start: Int, count: Int, after: Int) { }
override fun onTextChanged(text: CharSequence?, start: Int, before: Int, count: Int) { }
override fun afterTextChanged(text: Editable?) { validateEmpty() }
private fun validatePasswordText(): Boolean {
if (validateEmptyText(showError = false)) {
getParentInputLayout()?.isErrorEnabled = false
return true
}
return false
}
}
addTextChangedListener(textWatcher)
return textWatcher
}
fun EditText.validateEmailFormat(showError: Boolean = true): Boolean
{
// Do something checking the Email
return false
}
fun EditText.validatePasswordText(showError: Boolean = true): Boolean
{
// Do something checking the Password
return false
}
private fun EditText.getParentInputLayout(): TextInputLayout? {
if (parent is TextInputLayout) {
return parent as TextInputLayout
}
return null
}
Both setEmailValidationListener
and setPasswordValidationListener
are identical, except for the validation function they use respectively i.e. validateEmailFormat
and validatePasswordFormat
.
So I plan to refactor the two function common code into a common function as below
fun EditText.setupTextChangeListener(validatorFunc : (showError: Boolean) -> Boolean): TextWatcher {
val textWatcher = object : TextWatcher {
override fun beforeTextChanged(text: CharSequence?, start: Int, count: Int, after: Int) { }
override fun onTextChanged(text: CharSequence?, start: Int, before: Int, count: Int) { }
override fun afterTextChanged(text: Editable?) { validateEmpty() }
private fun validateEmpty(): Boolean {
if (validatorFunc(false)) {
getParentInputLayout()?.isErrorEnabled = false
return true
}
return false
}
}
addTextChangedListener(textWatcher)
return textWatcher
}
... where it basically just to send in validationFunc
as parameter to it.
However, I can't find any way of sending the EditText.validateEmailFormat
and EditText.validatePasswordFormat
into the validationFunc
function parameter.
How could I achieve that?
Extension functions are a cool Kotlin feature that help you develop Android apps. They provide the ability to add new functionality to classes without having to inherit from them or to use design patterns like Decorator.
Inside such an extension, there are multiple implicit receivers - objects whose members can be accessed without a qualifier. An instance of a class in which the extension is declared is called a dispatch receiver, and an instance of the receiver type of the extension method is called an extension receiver.
In particular, Kotlin extensions let you add functions to a class that you cannot modify. By using them, you will be able to call these new functions as if they were part of the original class. Similarly, you can use this mechanism to add new properties to existing classes. You can also extend Kotlin companion objects.
Some theory
Signature of extension functions is bit more complicated than in may look at first. The extension needs to have some reference to object of this class to be able to act upon it.
In fact the extension method
fun EditText.validateEmailFormat(showError: Boolean = true): Boolean
after decompiling to plain old java, looks like this:
public static final boolean validateEmailFormat(@NotNull EditText $receiver, boolean showError)
As it's (almost) impossible to change already-compiled Java class. So Kotlin (and quite possibly other languages that have concept of extension methods) uses static methods, with first parameter being receiver of extending class, to make it work.
Back to the business
Your validateEmailFormat
is in fact of type EditText.(Boolean) -> Boolean
and at the same time is of type (EditText, Boolean) -> Boolean
. So you need to do either of two things:
First you can make EditText.setupTextChangeListener
accept validatorFunc
as EditText.(Boolean) -> Boolean
or (EditText, Boolean) -> Boolean
instead of (Boolean) -> Boolean
.
Or you refrain from extending EditText
in fun EditText.validateEmailFormat(Boolean)
and make it plain Kotlin function, e.g. something like this fun validateEmailFormat(String, Boolean)
.
As you are extensively using extension functions, I assume the first option is correct solution for you.
fun EditText.validateEmailFormat()
can be passed as EditText::validateEmailFormat
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With