Reputation: 60341
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?
Upvotes: 7
Views: 4285
Reputation: 4112
fun EditText.validateEmailFormat()
can be passed as EditText::validateEmailFormat
.
Upvotes: 4
Reputation: 3250
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.
Upvotes: 9