Imagine a main App composable function, which has a file chooser for selecting a file and a call to ...
p
Imagine a main App composable function, which has a file chooser for selecting a file and a call to another composable function called listFiles that prints the content of the selected file by te file chooser. If i select two different files, the listFiles function is called two times. But if I select two times the same file, the listFiles function source code is not being executed for the second file. Even if no condition is checked for calling the function. How is that possible? Does Compose execute some "hidden" logic before execute a composable function that checks if the function has been called previously with exactly the same parameters and if so it does not execute the code?
k
You deleted your previous question around the same topic. The answer is still the same - you need to provide the code that people can look at and run on their machine. Not a piece of it. A standalone minimal reproducer that shows the issue, that can be copy-pasted and run as is with no modifications.
p
Hi Kirill, it is not a code problem, I already disscussed with two compose devs and the code is perfectly working. It's simply that Compose doesn't execute the code if the parameter it's the same. I'm trying to understand why, and can't find why in the official documentation. I hope someone knows it and will explain it here.
k
If you want a concrete answer, you need to provide a concrete problem, and not a subjective interpretation of it.
p
On the other hand, I already posted the code previously here, for a lot of hours no one answered, so I consider that the question was badly expressed and now that I know that it's not a source code problem, I think it's better to answer this way.
k
The code you posted was snippets, not a standalone thing that could be copy-pasted and run as-is. You can’t expect people to spend time on filling in the gaps on their side.
Copy code
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.WindowPlacement
import androidx.compose.ui.window.WindowPosition
import androidx.compose.ui.window.rememberWindowState
import org.pushingpixels.aurora.component.model.Command
import org.pushingpixels.aurora.component.projection.CommandButtonProjection
import org.pushingpixels.aurora.theming.auroraBackground
import org.pushingpixels.aurora.theming.marinerSkin
import org.pushingpixels.aurora.window.AuroraWindow
import org.pushingpixels.aurora.window.AuroraWindowTitlePaneConfigurations
import org.pushingpixels.aurora.window.auroraApplication
import java.io.File
import javax.swing.JFileChooser

fun main() = auroraApplication {
    val state = rememberWindowState(
        placement = WindowPlacement.Floating,
        position = WindowPosition.Aligned(Alignment.Center),
        size = DpSize(220.dp, 150.dp)
    )

    AuroraWindow(
        skin = marinerSkin(),
        title = "Aurora Demo",
        state = state,
        windowTitlePaneConfiguration = AuroraWindowTitlePaneConfigurations.AuroraPlain(),
        onCloseRequest = ::exitApplication
    ) {
        var text by remember { mutableStateOf("Hello, World!") }

        Row(
            horizontalArrangement = Arrangement.Center,
            verticalAlignment = Alignment.CenterVertically,
            modifier = Modifier.fillMaxSize().auroraBackground()
        ) {
            CommandButtonProjection(
                contentModel = Command(
                    text = text,
                    action = {
                        text = "Hello, Desktop!"
                        val fileChooser = JFileChooser()
                        fileChooser.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
                        val option = fileChooser.showOpenDialog(window)
                        if (option == JFileChooser.APPROVE_OPTION) {
                            val file: File = fileChooser.selectedFile
                            println("Folder Selected: ${file.name}")
                            for (child in file.listFiles()) {
                                println("\t${child.name}")
                            }
                        }
                    }
                )
            ).project()
        }
    }
}
This is a simple, standalone example of an Aurora button that opens a file chooser and prints the contents of the selected folder.
You can either reduce your code to the smallest possible thing that still reproduces the issue. Or you can work from this code towards your code until you have the reproducer. In any case, the total size of your code determines how much attention you’re going to get on Internet forums such as this. You need to show that you did your part in making it as small as possible, and self-contained.
p
Thank you, how can I import aurora?
I tryed with:
Copy code
implementation(compose.desktop.currentOs)
implementation(org.pushing-pixels)
but it gives error
really can't find how to import it in your github
k
https://github.com/kirill-grouchnikov/aurora#aurora-artifacts - click on badges to see instructions on how to add Aurora dependencies based on your build system. You don’t need Aurora, of course. You can replace all the bits above with Material counterparts.
p
ok @Kirill Grouchnikov thank you I added a very small change in your sample to demonstrate the issue
Copy code
fun main() = auroraApplication {
    val state = rememberWindowState(
        placement = WindowPlacement.Floating,
        position = WindowPosition.Aligned(Alignment.Center),
        size = DpSize(220.dp, 150.dp)
    )

    AuroraWindow(
        skin = marinerSkin(),
        title = "Aurora Demo",
        state = state,
        windowTitlePaneConfiguration = AuroraWindowTitlePaneConfigurations.AuroraPlain(),
        onCloseRequest = ::exitApplication
    ) {
        var text by remember { mutableStateOf("Hello, World!") }
        var folderChosenPath = remember { mutableStateOf( "") }

        Row(
            horizontalArrangement = Arrangement.Center,
            verticalAlignment = Alignment.CenterVertically,
            modifier = Modifier.fillMaxSize().auroraBackground()
        ) {
            CommandButtonProjection(
                contentModel = Command(
                    text = text,
                    action = {
                        text = "Hello, Desktop!"
                        val fileChooser = JFileChooser()
                        fileChooser.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
                        val option = fileChooser.showOpenDialog(window)
                        if (option == JFileChooser.APPROVE_OPTION) {
                            val file: File = fileChooser.selectedFile
                            println("Folder Selected: ${file.name}")
                            for (child in file.listFiles()) {
                                println("\t${child.name}")
                            }

                            folderChosenPath.value = file.path
                        }
                    }
                )
            ).project()
        }

        Print(folderChosenPath)
    }
}

@Composable
fun Print(folderPath: MutableState<String>) {
    var folder = File(folderPath.value)
    System.out.println("XXXXXXXX Print called")
}
now check what happens if you select two followed times the same folder, Print(folderChosenPath) will be called only the first time, if you select the same folder in a row, it will not be printed again, but if you select a different one, it is printed.
that was the behaviour I'm trying to understand from Compose
and thank you very much for your great sample code
k
Why does
Print
need to be
@Composable
?
p
it is a super small sample, in my case, print does some job, like printing the folder contents etc... it's only to show you that it is not being called twice if you select two times the same folder
my intention is to understand why that happens
which kind of implementation haves Compose to do it this way
I come from sequential progamming, these are my first steps in Compose and declarative logic, pretty sure it has sense but after reading tutorials and watching video tutorials and doing my first test apps I'm facing issues with some things like this, learning why this happens will help me
k
Since the input parameter to
Print
doesn’t change, Compose skips that recomposition. These are not imperative functions that are executed every time.
Hence my question on why it’s marked as
@Composable
p
So, to understand it, Does compose store previous call to each composable functions, and if the current call haves the same parameter values, doesn't execute it?
p
Wow, perfectly explained there. Is what I supposed. Thank you very much!