Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

View Binding with Kotlin 1.6.0 not working #46

Closed
vsxed opened this issue Jan 20, 2022 · 5 comments
Closed

View Binding with Kotlin 1.6.0 not working #46

vsxed opened this issue Jan 20, 2022 · 5 comments

Comments

@vsxed
Copy link

vsxed commented Jan 20, 2022

Hey there,

as of today i tried migrating an older app and now i am required to use Kotlins Android View Binding with kotlin 1.6.0.

I followed the example in the readme but i cant make it to work.
This is how my code looks:

class DiscoveredDeviceModule(
    val context: Context,
    private val callback: DeviceModuleCallbackListener?
) : ItemModule<DiffableDevice>() {
    init {
        config {
            layoutResource = R.layout.component_discover_bt_list_item

            firstBindAnimation = AnimatorInflater.loadAnimator(
                context,
                R.animator.animator_new_bt_device_discovered
            )
        }

        onBind { item, viewBinder, _ ->
            viewBinder.bindings(ComponentDiscoverBtListItemBinding::bind).run {
                btListItemTitle.text = item.getReadableName(context.resources)
                // PushDownAnim.setPushDownAnimTo(btListItemWrapper)

                btListItemWrapper.setOnClickListener {
                    btListItemProgress.visibility = View.VISIBLE
                    callback?.onClick(item)
                }
            }
        }
    }

    interface DeviceModuleCallbackListener {
        fun onClick(device: DiffableDevice) {}
    }
}

Everytime the onBind should have been called, nothing appears in the view.
Any help?

The version i'm using is 2.1.1

@idanatz
Copy link
Collaborator

idanatz commented Jan 20, 2022

Hey,
onBind should be called regardless of viewbindings.
it means that the item is not rendering in your RecycerView.

  1. Please add the XMLs where the RecyclerView is defined and R.layout.component_discover_bt_list_item
  2. have you tried it without the the onBindAnimation?
  3. does your RecyclerView has LayoutManager attached?

@vsxed
Copy link
Author

vsxed commented Jan 20, 2022

Hey, thanks for the fast reply!

onBind is called correctly, since the breakpoint stops at the root of onBind { .. }

R.layout.component_discover_bt_list_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/bt_list_item__wrapper"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <View
            android:id="@+id/bt_list_item__prefix"
            android:layout_width="4dp"
            android:layout_height="4dp"
            android:layout_marginStart="@dimen/component_discover_bt_horizontal_spacing"
            android:layout_marginEnd="24dp"
            android:background="@drawable/ic_dot"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/bt_list_item__title"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/bt_list_item__title"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:paddingStart="0dp"
            android:paddingTop="12dp"
            android:paddingEnd="64dp"
            android:paddingBottom="12dp"
            android:singleLine="true"
            android:textColor="@color/colorLightGrey"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toEndOf="@id/bt_list_item__prefix"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="Device name" />

        <ProgressBar
            android:id="@+id/bt_list_item__progress"
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginEnd="@dimen/component_discover_bt_horizontal_spacing"
            android:indeterminateTint="@color/colorLightGrey"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="@id/bt_list_item__title"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@drawable/component_list_item_divider"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

The actual RecyclerView layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

...

<androidx.recyclerview.widget.RecyclerView
            android:id="@+id/discover_bt__device_list__devices"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp"
            android:isScrollContainer="false"
            android:nestedScrollingEnabled="false"
            android:orientation="vertical"
            android:paddingBottom="32dp"

            <!-- LayoutManager is set here -->
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"

            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/discover_bt__device_list__status"
            tools:itemCount="24"
            tools:listitem="@layout/component_discover_bt_list_item" />
...
</androidx.constraintlayout.widget.ConstraintLayout>

And heres the relevant Fragment code where it is actucally attached:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
...
adapter = OneAdapter(discover_bt__device_list__devices!!) {
            itemModules += DiscoveredDeviceModule(
                requireContext(),
                object : DiscoveredDeviceModule.DeviceModuleCallbackListener {
                    override fun onClick(device: DiffableDevice) {
                        viewModel.apply {
                            viewModel.stopScanningForDevices()

                            binding?.let {
                                // add extras to tell the fragment to create a shared transition
                                val navExtraInfo = FragmentNavigatorExtras(
                                    it.discoverBtContentImage to "discover_image",
                                    it.discoverBtContentInfo to "discover_descr_text"
                                )

                                findNavController().navigate(
                                    DiscoverBluetoothFragmentDirections.routeFromDiscoverBluetoothToDiscoveryPersonalization(
                                        deviceMacAddress = device.uuid,
                                        suggestedName = device.getReadableName(resources),
                                        deviceQrCode = null,
                                    ),
                                    navExtraInfo
                                )
                            }
                        }
                    }
                }
            )
        }

        adapter.setItems(
            btViewModel.discoveredDevices.value?.map { device -> DiffableDevice(device) }
                ?: listOf()
        )
...
}
  1. Removing the animation makes no difference.
  2. as you can see above in the xml: it has. But also doing it programmatically before attaching the adapter, it does not seem to work.

Before switching to View Binding, everything worked fine.

@idanatz
Copy link
Collaborator

idanatz commented Jan 23, 2022

I've updated the sample project to Kotlin 1.6.0 and the ViewBindings example works without any special issues 🤷🏻‍♂️

Have you verified your implementation against the sample project by any chance?
https://github.com/ironSource/OneAdapter/blob/develop/sample/app/src/main/java/com/idanatz/sample/examples/binding/view_binding/ViewBindingActivity.kt

Its very simple example but I've used this feature in bigger and more complex scenarios with no issues

@vsxed
Copy link
Author

vsxed commented Jan 25, 2022

Thanks so far. Will take a look at it and report back.

@vsxed
Copy link
Author

vsxed commented Jan 25, 2022

Okay, this issue can be closed.
Seems like it was an underlying View Binding issue.

Inside the Fragment i got an

...
  <include  layout="@layout/component_discover_device_list" />
...

without an id, so the View Binding could not reference it (and it inner children) properly.
This resulted in the above error, since all child views may appear in the debugging tools as valid views, but it was not possible to change them programmatically.

The fix was to give the include also a reference

...
        <include
            android:id="@+id/innerReference"
            layout="@layout/component_discover_device_list" />
...

and then use them like this

binding?.innereReference?.btListItemTitle?.text = "anything"

Now it seems to work fine.

@vsxed vsxed closed this as completed Jan 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants