Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Data Binding: Missing return statement in generated code when calling custom binding adapter more than once

I am using the android data binding library and MVVM architecture. In the xml layout I define a variable named viewModel of type myViewModel. The layout has several TextInputEditText for which I used the following custom binding adapter:

//makes the drawable_right of the TextView clickable
@SuppressLint("ClickableViewAccessibility")
@BindingAdapter("onDrawableRightClick")
inline fun TextView.setOnDrawableRightClick(crossinline f: () -> Unit) {
    this.setOnTouchListener(View.OnTouchListener { _, event ->
        if (event.action == MotionEvent.ACTION_UP) {
            if (event.rawX >= this.right - this.paddingRight - this.compoundDrawables[DRAWABLE_RIGHT].bounds.width()) {
                f()
                return@OnTouchListener true
            }
        }
        false
    })
}

In the layout I add app:onDrawableRightClick="@{() -> viewModel.doThing()}" to just one of the TextInputEditText and click run. Everything works, no problem.

Now I go back and add app:onDrawableRightClick="@{() -> viewModel.doOtherThing()}" to the second TextInputEditText. This time compilation fails with error: missing return statement.

The error is in MyFragmentBindingImpl (generated), in this block of code:

public final kotlin.Unit _internalCallbackInvoke(int sourceId ) {
    switch(sourceId) {
        case 1: {
            // localize variables for thread safety
            // viewModel
            com.example.MyViewModel viewModel = mViewModel;
            // viewModel != null
            boolean viewModelJavaLangObjectNull = false;

            viewModelJavaLangObjectNull = (viewModel) != (null);
            if (viewModelJavaLangObjectNull) {

                   viewModel.doOtherThing();
            }
            return null;
        }
        case 2: {
            // localize variables for thread safety
            // viewModel
            com.example.MyViewModel viewModel = mViewModel;
            // viewModel != null
            boolean viewModelJavaLangObjectNull = false;

            viewModelJavaLangObjectNull = (viewModel) != (null);
            if (viewModelJavaLangObjectNull) {

                viewModel.doThing();
            }
            return null;
        }  
    }
}

There is neither a default case nor a return statement outside of the switch. This causes the error but I was pretty sure that the default case isn't necessary when every case is handled... Anyways, when I go back to xml and remove one of the listener bindings, MyFragmentBindingImpl changes to this:

public final kotlin.Unit _internalCallbackInvoke(int sourceId ) {
    // localize variables for thread safety
    // viewModel
    com.example.MyViewModel viewModel = mViewModel;
    // viewModel != null
    boolean viewModelJavaLangObjectNull = false;

    viewModelJavaLangObjectNull = (viewModel) != (null);
    if (viewModelJavaLangObjectNull) {

      viewModel.doThing();
    }
    return null;
}

The compiler is happy again, but I need to use the binding adapter more than once. How can I make the library add a return statement? Is there a workaround?

I'm using Android Studio 3.4 Preview. Thanks all

like image 568
AaronJ Avatar asked Nov 23 '18 09:11

AaronJ


People also ask

What is binding adapter in data binding Android?

Binding adapters are responsible for making the appropriate framework calls to set values. One example is setting a property value like calling the setText() method. Another example is setting an event listener like calling the setOnClickListener() method.

How check data binding is null in Android?

Generated data binding code automatically checks for null values and avoid null pointer exceptions. For example, in the expression @{user.name} , if user is null, user.name is assigned its default value of null . If you reference user. age , where age is of type int , then data binding uses the default value of 0 .

Can I use ViewBinding and data binding together?

As you've seen, there's no reason you can't use both Data Binding and View Binding on the same project. By default, the view binder compiler generates a binding class for each XML file. But, if you want to use Data Binding instead, you have to add the layout tag, as root, to the XML file.

Which is better view binding or data binding in Android?

ViewBinding vs DataBindingThe main advantages of viewbinding are speed and efficiency. It has a shorter build time because it avoids the overhead and performance issues associated with DataBinding due to annotation processors affecting DataBinding's build time.


1 Answers

@SuppressLint("ClickableViewAccessibility")
@BindingAdapter("onDrawableEndClick")
fun setOnDrawableEndClick(view: TextView, listener: OnCompoundDrawableClickListener?) {
    val padding = 10
    if (listener != null) {
        view.setOnTouchListener { _, event ->
            if (event.action == MotionEvent.ACTION_DOWN) {
                if (view.compoundDrawables[DRAWABLE_RIGHT] == null) return@setOnTouchListener false
                else if (event.rawX >= (view.right - view.compoundDrawables[DRAWABLE_RIGHT].bounds.width() - padding)) {
                    listener.onDrawableEnd()
                    return@setOnTouchListener true
                }
            }
            return@setOnTouchListener false
        }
    }
}

try something like this i am using a custom interface for the listener(OnCompoundDrawableClickListener)

like image 51
Abraham Mathew Avatar answered Sep 27 '22 18:09

Abraham Mathew