Skip to content
This repository has been archived by the owner on Jun 1, 2024. It is now read-only.

Creating listview programmatically will result in crash with "java.lang.IllegalArgumentException: RecyclerView Id can't be -1" #1842

Closed
brianchu opened this issue Feb 13, 2023 · 7 comments
Labels
bug Something isn't working

Comments

@brianchu
Copy link

brianchu commented Feb 13, 2023

Please provide all the information requested. Issues that do not follow this format are likely to stall.

Description

I have a Compose view to include a listview (as AndroidView) and pass in the data (value) directly as dataSource. However, when it scrolls to the end, the app crash with


  java.lang.IllegalArgumentException: RecyclerView Id can't be -1
                 	at br.com.zup.beagle.android.view.viewmodel.ListViewIdViewModel.markHasCompletelyLoaded(ListViewIdViewModel.kt:147)
                 	at br.com.zup.beagle.android.components.ListView$configRecyclerViewScrollListener$1.onScrolled(ListView.kt:175)
                 	at androidx.recyclerview.widget.RecyclerView.dispatchOnScrolled(RecyclerView.java:5347)


Steps To Reproduce

Provide a detailed list of steps that reproduce the issue.

  1. Create a native component using Compose
  2. Create a listview and pass in all correct data.
  3. The dataSource is direct data, so there is no expression, just value (array of hash map)
  4. It will show correctly when start
  5. Scroll to the end, it crashes.

Expected Results

No crash when scrolling in any way.

The view.id is -1 (NO ID) and component's id doesn't seem to set.

Code example, screenshot, or link to a repository:

@Composable
fun ListViewWrapper(state: SomeExtendListViewData, rootView: RootView) {

    Box() {
        state.dataSource?.let { data: List<Any> ->
            AndroidView(
                factory = {
                    val listView = ListView(
                        direction = state.direction,
                        context = state.context,
                        onInit = state.onInit,
                        dataSource = Bind.Value(data),
                        templates = state.templates,
                    )

                    listView.buildView(rootView)
                }
            )
        }
    }
}
@brianchu brianchu added the bug Something isn't working label Feb 13, 2023
@brianchu
Copy link
Author

The reason why I pass in data directly is because I want to manipulate them before giving to the list view. I tried onInit first but it won't work since it won't happen until window is attached. so I think since I create my own Compose to wrap a Beagle component, I will bind the data myself and once I get the data and after I manipulate them, I pass it to the list view created programmatically.

@Tiagoperes
Copy link
Contributor

Tiagoperes commented Feb 13, 2023

Hello Brian. Hope you're well!

Before addressing this issue, I must make some remarks:

  • Beagle has lots and lots of tests, none of them involves Jetpack Compose. Beagle was never supposed to work with Compose and this is untested territory. It might work because this compatibility is implemented by Android itself, but we can't make any guarantees, mainly because Compose layout will probably not play well with Yoga Layout (used by Beagle).
  • Beagle's default components were not supposed to be called programmatically. They have been designed to be directly rendered by a Server Driven View.

Nonetheless, this is an unexpected error and might be a reflection of a bigger problem, so we'll investigate it and keep you posted.

You also said that you need to manipulate the data before passing it to the component. The recommended way of manipulating data in Beagle is not to create a new custom component, but instead, create a new custom operation. Let's say you have a List of numbers and you want to pass their summed values to a component, you'd use the expression @{sum(data)}. sum, in this example, is an operation, you can create your own operations to manipulate any kind of data without having to create a custom component.

About SwiftUI and Compose

Just to make it clear, we're not ignoring SwiftUI and Compose, but Beagle would need a full rewrite to not just support them, but actually take advantage of their architecture.

We're making such rewrite, it's called Nimbus. We didn't call it Beagle because it would create some unnecessary confusion. Don't worry, Beagle will still be maintained. Nimbus is not ready for production yet, but we've recently published the first beta.

@brianchu
Copy link
Author

brianchu commented Feb 13, 2023

Thanks for your reply.

How do you add custom action to the dataSource of a listview?

"dataSource": "@{fixdata(@{data.foo.bar})}"

doesn't work for me as my operation (fixdata) never execute.

@brianchu
Copy link
Author

brianchu commented Feb 14, 2023

😆 It should be
"dataSource": "@{fixdata(data.foo.bar)}"
This one works perfectly.

@Tiagoperes
Copy link
Contributor

I'm glad it worked Brian! I'll still check the index problem.

@brianchu
Copy link
Author

brianchu commented Feb 15, 2023

  • I also did a similar one in Android view (not Compose), very similar to gridView and it has no issue.
  • I added a BeagleFlexView to wrap around the listView in my Compose example, same issue. It look like:
@Composable
fun ListViewWrapper(state: MyState, rootView: RootView) {

    Box() {
        state.dataSource?.let { data: List<Any> ->
            AndroidView(
                factory = {
                    val flexView = BeagleFlexView(rootView)
                    val listView: ListView = ListView(
                        direction = state.direction,
                        context = state.context,
                        onInit = state.onInit,
                        dataSource = Bind.Value(data),
                        templates = state.templates,
                    )

                    flexView.addView(listView.buildView(rootView), Style())
                    flexView
                }
            )
        }
    }
}

@Tiagoperes
Copy link
Contributor

Since this problem only happens with Jetpack Compose, I consider fixing it as a new feature. As stated before, Beagle was not initially made for Compose.

Unfortunately we don't have a dedicated team for Beagle right now and we'll only be fixing critical bugs for the time being. Community pull requests will be still welcomed.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants