https://kotlinlang.org logo
#compose
Title
# compose
n

Nat Strangerweather

08/05/2022, 2:35 PM
Hi, I am getting an indexOutOfBoundsException when I initially install my app on a fresh emulator. Is there something really obvious in my code snippet that would cause this to happen? 🧵
Copy code
VerticalGrid(
        columns = 7, modifier = Modifier
            .background(
                color = findColor(accentColor),
                shape = RoundedCornerShape(8.dp)
            )
            .padding(start = 10.dp, end = 10.dp, top = boardPadding, bottom = boardPadding)
    ) {
       boardLetters?.forEachIndexed { index, letter ->
            MainPiece(
                letter, index,
                state = MainPieceComposableState(
                    visible =
                    if (savedValues != null && savedValues?.isNotEmpty() == true
                        && isReloaded == false
                    ) visible!![index] else true,
                    enabled = if (savedValues != null && savedValues?.isNotEmpty() == true
                        && isReloaded == false
                    ) enabled!![index] else true
                )
            )
        }
l

Lukasz Kalnik

08/05/2022, 2:57 PM
Where do
visible!!
and
enabled!!
come from? Look like the most likely candidates, as you access them by
index
.
l

Landry Norris

08/05/2022, 2:58 PM
Which line does the IndexOutOfBoundsException point to?
I’d add a print before that line that prints out the index and the size of the array. That will tell you what’s wrong. Is boardLetters larger than visible? Is it larger than enabled? How is the size of each set?
n

Nat Strangerweather

08/05/2022, 2:59 PM
They come from a room database. Initially they are
true
but when the database exists they come from there. Which is why I check if the saved values exist...
l

Lukasz Kalnik

08/05/2022, 3:00 PM
It would be helpful also to check if they are the right size
Do you use any business logic class, like a ViewModel?
n

Nat Strangerweather

08/05/2022, 3:00 PM
yes, I can show you if you like
l

Lukasz Kalnik

08/05/2022, 3:01 PM
Then it would be easier to set the values from the room database to
boardLetters
already there.
n

Nat Strangerweather

08/05/2022, 3:01 PM
@Landry Norris thanks will try that
l

Lukasz Kalnik

08/05/2022, 3:01 PM
the advantage is that you would have all the logic in one place and also you could unit test it.
n

Nat Strangerweather

08/05/2022, 3:02 PM
Copy code
**Repository**
 val arr = Array(9) {
        Letter("A", 1)
    } + Array(2) {
        Letter("B", 3)
    } + Array(2) {
        Letter("C", 3)
    } + Array(4) {
        Letter("D", 2)
    } etc...

**ViewModel**

private fun shakeLetterBag(count: Int): Array<Letter> {
        return repository.arr.toList()
            .shuffled()
            .take(count).toTypedArray()
    }

var boardLetters = MutableLiveData(shakeLetterBag(28))

**GameBoard**
VerticalGrid(
        columns = 7, modifier = Modifier
            .background(
                color = findColor(accentColor),
                shape = RoundedCornerShape(8.dp)
            )
            .padding(start = 10.dp, end = 10.dp, top = boardPadding, bottom = boardPadding)
    ) {
       boardLetters?.forEachIndexed { index, letter ->
            MainPiece(
                letter, index,
                state = MainPieceComposableState(
                    visible =
                    if (savedValues != null && savedValues?.isNotEmpty() == true
                        && isReloaded == false
                    ) visible!![index] else true,
                    enabled = if (savedValues != null && savedValues?.isNotEmpty() == true
                        && isReloaded == false
                    ) enabled!![index] else true
                )
            )
        }
@Landry Norris The exception points to this:
Copy code
) visible!![index] else true,
l

Lukasz Kalnik

08/05/2022, 3:04 PM
It means that the
visible
size is smaller or equal than the
index
n

Nat Strangerweather

08/05/2022, 3:05 PM
I'm not sure how that is possible
l

Lukasz Kalnik

08/05/2022, 3:05 PM
Can you post the code snippet where you set
visible
from room database?
l

Landry Norris

08/05/2022, 3:05 PM
boardLetters would have a size of 28, so index is between 0 and 27
Why is visible both a boolean and an array? The type system should prevent this.
Same with enabled.
l

Lukasz Kalnik

08/05/2022, 3:07 PM
This is correct.
visible =
(Boolean) is the named parameter of the
MainPieceComposableState
.
n

Nat Strangerweather

08/05/2022, 3:07 PM
I'm a bit lost now tbh 🙂
l

Lukasz Kalnik

08/05/2022, 3:07 PM
visible!![index]
is an Iterable of booleans
There is no conflict
Don't worry @Nat Strangerweather 😉
l

Landry Norris

08/05/2022, 3:07 PM
I see. I didn’t catch that it was a named function arg.
l

Lukasz Kalnik

08/05/2022, 3:09 PM
Just add a
println("visible size: ${visible.size})
and the same for enabled inside of your
boardLetters?.forEachIndexed
Tell us what they output
n

Nat Strangerweather

08/05/2022, 3:09 PM
ok
l

Landry Norris

08/05/2022, 3:10 PM
If the size of either is less than 28, we would expect an index out of bounds, since boardLetters has a size of 28 in the snippet.
n

Nat Strangerweather

08/05/2022, 3:11 PM
They both come up as 1
l

Lukasz Kalnik

08/05/2022, 3:11 PM
There is your answer
Paste a code snippet where you load the data from room database
And where you write it
n

Nat Strangerweather

08/05/2022, 3:13 PM
Actually, I ran it again in a LaunchedEffect and it's null
Ok, I'll post the snippet
l

Lukasz Kalnik

08/05/2022, 3:15 PM
Don't run the
println()
in LaunchedEffect, as it will run parallel to the rest of your code
Just run it with the rest of the code which accesses the
visible
Array (or List, whatever you use)
n

Nat Strangerweather

08/05/2022, 3:17 PM
Do you mean where I load the data as in the Dao etc?
l

Lukasz Kalnik

08/05/2022, 3:17 PM
Forget it, I just responded to what you wrote about the
null
you got
But we anyway already know the size of the
visible
is 1
Sorry for confusing you.
n

Nat Strangerweather

08/05/2022, 3:18 PM
no problem , tahnks for helping me!
l

Lukasz Kalnik

08/05/2022, 3:18 PM
Just post the room read/write snippet
n

Nat Strangerweather

08/05/2022, 3:20 PM
Copy code
val readVisible: LiveData<List<Boolean>> = savedValuesDao.readVisible()
    val readEnabled: LiveData<List<Boolean>> = savedValuesDao.readEnabled()
l

Lukasz Kalnik

08/05/2022, 3:20 PM
OK, these are the declarations, but we need the place where you actually read/write something there
Is this project on GitHub? So you don't have to post snippets over and over again.
n

Nat Strangerweather

08/05/2022, 3:21 PM
Copy code
fun saveValues(index: Int) {
        if (savedValues != null) {
            if (savedValues!!.isEmpty()) {
                savedViewModel.addValues(
                    SavedValues(
                        index,
                        visible = true,
                        enabled = true,
                        boardLetters = boardLetters!![index].name,
                        boardLettersValue = boardLetters!![index].value,
                        validated = false
                    )
                )
            } else {
                savedViewModel.updatePieces(
                    SavedPieces(
                        index,
                        boardLetters!![index].name,
                        boardLetters!![index].value
                    )
                )
            }
        }
    }
yes it's on github
l

Lukasz Kalnik

08/05/2022, 3:22 PM
is it public?
Just post the link then, it will be easier to check what's wrong there.
n

Nat Strangerweather

08/05/2022, 3:22 PM
no, unfortunately I am not confident enough with my code for it to be public
l

Lukasz Kalnik

08/05/2022, 3:23 PM
Ah ok
The code you posted doesn't write anything to the Dao though
n

Nat Strangerweather

08/05/2022, 3:24 PM
it does through my viewModel and Repository
plus when I check the values on the database they are all there
this is why I have no problem after the initial install
l

Lukasz Kalnik

08/05/2022, 3:25 PM
If the values are in the db, then maybe the problem is where you read them?
n

Nat Strangerweather

08/05/2022, 3:25 PM
yes, makes sense
I need to find the right snippet 😉
l

Lukasz Kalnik

08/05/2022, 3:25 PM
Do you have unit tests for your ViewModels and repositories?
That's why I meant that seeing the project would make easier hunting the bug 😉
And helping you.
n

Nat Strangerweather

08/05/2022, 3:26 PM
lol, I can give you access
l

Lukasz Kalnik

08/05/2022, 3:28 PM
I'm
lukaszkalnik
on GitHub
n

Nat Strangerweather

08/05/2022, 3:29 PM
I've made it public
l

Lukasz Kalnik

08/05/2022, 3:29 PM
Great
We've all been beginners (and still are), don't worry!
Which file is problematic?
l

Lukasz Kalnik

08/05/2022, 3:38 PM
One thing which would be helpful, to write unit tests for your viewmodels/repositories. That would help catch bugs and edge cases.
And also move the logic out of the composables and into viewmodels.
n

Nat Strangerweather

08/05/2022, 3:40 PM
Yes, true, I need to learn testing.
l

Lukasz Kalnik

08/05/2022, 3:40 PM
E.g. this should be rather in viewmodel:
Copy code
if (savedValues != null && savedValues?.isNotEmpty() == true
                        && isReloaded == false
                    ) visible!![index] else true
n

Nat Strangerweather

08/05/2022, 3:40 PM
I see
l

Lukasz Kalnik

08/05/2022, 3:41 PM
And then just pass the computed value to the composable
Ok, so I started the app fresh and there is indeed no problem. Beautiful UI by the way 👍
Copy code
2022-08-05 17:42:45.789 26698-26698 System.out              com.strangerweather.words            I  visible.size: 28
2022-08-05 17:42:45.789 26698-26698 System.out              com.strangerweather.words            I  enabled.size: 28
2022-08-05 17:42:45.790 26698-26698 System.out              com.strangerweather.words            I  index: 25
2022-08-05 17:42:45.791 26698-26698 System.out              com.strangerweather.words            I  visible.size: 28
2022-08-05 17:42:45.791 26698-26698 System.out              com.strangerweather.words            I  enabled.size: 28
2022-08-05 17:42:45.792 26698-26698 System.out              com.strangerweather.words            I  index: 26
2022-08-05 17:42:45.792 26698-26698 System.out              com.strangerweather.words            I  visible.size: 28
2022-08-05 17:42:45.792 26698-26698 System.out              com.strangerweather.words            I  enabled.size: 28
visible and enabled have both size 28
What did you do to reproduce the bug?
n

Nat Strangerweather

08/05/2022, 3:43 PM
Thanks! 🙂
I just run the project on fresh emulators
l

Lukasz Kalnik

08/05/2022, 3:44 PM
I run it fresh, and it works
n

Nat Strangerweather

08/05/2022, 3:44 PM
odd
l

Lukasz Kalnik

08/05/2022, 3:45 PM
I run it on a real phone though, not an emulator
although it should not matter I think
n

Nat Strangerweather

08/05/2022, 3:46 PM
I have tried it on multiple emulators and it crashes with the same complaint
l

Lukasz Kalnik

08/05/2022, 3:46 PM
Did you try on a real phone?
n

Nat Strangerweather

08/05/2022, 3:46 PM
it works on my phone and my son's phone
l

Lukasz Kalnik

08/05/2022, 3:46 PM
I started it subsequently and it still works (on the same device)
It would be worse if it would work on emulators, but wouldn't on real phones
n

Nat Strangerweather

08/05/2022, 3:47 PM
Thanks, in any case, it's reassuring that it works for you!
l

Lukasz Kalnik

08/05/2022, 3:48 PM
It also works on my emulator 🤷
n

Nat Strangerweather

08/05/2022, 3:48 PM
wow, maybe it's because I am on Electric Eel?
l

Lukasz Kalnik

08/05/2022, 3:49 PM
My emulator is API level 30
My device is quite old, Android 9
n

Nat Strangerweather

08/05/2022, 3:49 PM
Ok, I've been testing on 30 to Tiramisu
l

Lukasz Kalnik

08/05/2022, 3:49 PM
Ah, you mean Android Studio Electric Eel
n

Nat Strangerweather

08/05/2022, 3:50 PM
yes
l

Lukasz Kalnik

08/05/2022, 3:50 PM
Yes, I use the Dolphin
n

Nat Strangerweather

08/05/2022, 3:50 PM
aaah
l

Lukasz Kalnik

08/05/2022, 3:50 PM
Probably something with their emulator is broken, it's still canary
Your game is ok!
n

Nat Strangerweather

08/05/2022, 3:50 PM
yes, and the latest canary
l

Lukasz Kalnik

08/05/2022, 3:50 PM
Canary means anything can be broken...
There's no guarantees 😉
n

Nat Strangerweather

08/05/2022, 3:51 PM
I can't believe the number of hours I spent on this "bug"!!
l

Lukasz Kalnik

08/05/2022, 3:51 PM
Better use a stable one, or beta version
Or, if you encounter a bug, make sure it's not the IDE
n

Nat Strangerweather

08/05/2022, 3:51 PM
yeah, lesson learnt!
l

Lukasz Kalnik

08/05/2022, 3:51 PM
👍
n

Nat Strangerweather

08/05/2022, 3:51 PM
tahnk you so much, you're very kind!
l

Lukasz Kalnik

08/05/2022, 3:52 PM
No problem
You're welcome!
26 Views