Reputation: 713
I am using data binding in my current application, and so far so good. However, when I tried to use it with a custom data binding adapter I wrote for my custom view, I got an error from auto generated file as the title says, missing return statement. This error does not occur when I used this data binding on only one view, but more than one gives the error. Below are my custom view and adapters, and usage in xml file. I already checked the answer of kinda duplicated question but it doesn't worked in my case, and does not have enough explanation.
class NeonTextView(context: Context, attrs: AttributeSet) : TextView(context, attrs) {
private val drawableClear: Drawable?
get() = ContextCompat.getDrawable(context, R.drawable.ic_clear)
lateinit var actionMethod: () -> Unit
lateinit var clearMethod: () -> Unit
var hasActionMethod = false
var hasClearMethod = false
init {
setupAttributes(attrs)
}
private fun setupAttributes(attrs: AttributeSet) {
val typedArray =
context.theme.obtainStyledAttributes(attrs, R.styleable.NeonTextView, 0, 0)
hasActionMethod = typedArray.getBoolean(
R.styleable.NeonTextView_hasActionMethod,
false
)
hasClearMethod = typedArray.getBoolean(
R.styleable.NeonTextView_hasClearMethod,
false
)
typedArray.recycle()
}
override fun onTextChanged(
text: CharSequence?,
start: Int,
lengthBefore: Int,
lengthAfter: Int
) {
text?.let { text ->
drawableClear?.let {
it.setBounds(0, 0, it.intrinsicWidth, it.intrinsicHeight)
}
setCompoundDrawablesWithIntrinsicBounds(
null,
null,
if (text.isNotEmpty()) drawableClear!! else null,
null
)
}
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
event?.let {
return when (it.action) {
ACTION_DOWN -> return true
ACTION_UP -> {
if (compoundDrawables[2] == null && hasActionMethod) {
actionMethod()
} else {
if (it.x > (width - paddingRight - compoundDrawables[2]!!.intrinsicWidth)) {
if (hasClearMethod) clearMethod()
text = ""
} else {
if (hasActionMethod) actionMethod()
}
}
performClick()
true
}
else -> false
}
}.run {
return false
}
}
override fun performClick(): Boolean {
super.performClick()
return true
}
}
And here is my binding adapters for binding methods that are used inside this custom text view:
@BindingAdapter("actionMethod")
fun NeonTextView.setActionMethod(actionMethod: () -> Unit) {
this.actionMethod = actionMethod
this.hasActionMethod = true
}
@BindingAdapter("clearMethod")
fun NeonTextView.setClearMethod(clearMethod: () -> Unit) {
this.clearMethod = clearMethod
this.hasClearMethod = true
}
And here is how I applied inside xml file:
<com.android.platform.NeonTextView
android:id="@+id/textViewSectionField"
style="@style/HeaderTextView.SubHeader"
app:hasActionMethod="true"
app:actionMethod="@{() -> viewModel.getDepartmentList()}"/>
Any ideas why I am getting error from generated file when I used this binding in more than one view inside xml?
Thanks in advance.
Upvotes: 3
Views: 1366
Reputation: 2085
The problem is with Java<->Kotlin compatibility. In Kotlin if you declare function
interface Func {
fun test(): Unit {
}
}
And use it from java
class FuncImpl implements Func {
@Override
public Unit test() {
return Unit.INSTANCE;
}
}
Note, please, that in that case in java code you need return
statement. The same is for lambdas.
So when you set up lambda from xml using databinding, it's treated as java's lambda, so generated code wasn't correctly processed in that case.
Upvotes: 2