Hi ! In my application I am using Navigation. But ...
# compose
l
Hi ! In my application I am using Navigation. But in one of my pushed pages, I mean in the composable which defines this page, I need to detect when application come back in the foreground, in order to update it. Let's call
MainActivity
the activity which defines the navigation, and
TargetComposable
the composable of the pushed page. How can I force a reload of
TargetComposable
when application is back in foreground ? Is using
MainActivity
's
onStart()
method mandatory (and can it lead to a kind a mess, coupled with Navigation) ? Or is there a simpler solution ?
I've tried this, but I loose my navigation state on reload.
In fact, I just need a way to force recomposition of the current page whenever the application is put in background then comes again in the foreground. Because even a simple
println
command is not triggered in such case inside the current page's Composable.
Does someone has a good resource / a good blog about the navigation and the application going into backward and foreward ?
i
"Forcing a reload" is really the anti-thesis of a state driven UI like Compose
๐Ÿ‘ 1
Can you explain what state is changing? What is the source of truth for that state? Why isn't that source of truth already observing and notifying you when the state is changed?
l
Here, is the code for the page I need to refresh : more explanations in the next message
In this engines pages, I rely on an utility class I've written myself. And with it, I fill two
LazyColum
, each with two list of String I got from two different functions of my utility method.
The first list is likely to evolve as some packages are added and removed from PlayStore : because a discovery is made on applications which handles
Intent
for Chess OEX engine.
While the second list is unlikely to evolve based on external circumstances : it is based on application internal files, which the second utility method handle for me.
The problem I faced, is that when setting the application in the background, installing/removing some Chess OEX application, then going back : the first list was not updated.
I think I've a workaround with lifecycle, but it seems a kind "buggy", as the
println
command seems to be always executed :
Copy code
SideEffect {
            println("Activating page again")
            storeEngines = enginesUtils.getMyStoreEnginesNames()
        }
i
It sounds like what you actually need is a
Flow<Array<String>>
that uses
PackageManager
to observe additions and removals of packages. Then your UI would automatically recompose as that set of engines change
๐Ÿ‘ 1
One of my own personal apps does something similar (but with a particular ContentProvider
Intent
): https://github.com/muzei/muzei/blob/main/android-client-common/src/main/java/com/google/android/apps/muzei/room/InstalledProviders.kt
๐Ÿ‘ 1
For your own internal application files, it sounds like you should do something similar where you have some repository class that manages the addition/removal of these application internal files and returns a flow of the current list of files that is always up to date
๐Ÿ‘ 1
l
Thank you for your suggestions. ๐Ÿ™‚
I've also managed to solve my issue with a
SideEffect
block : but the fact is that for now, it causes a infinite recomposition loop. So I still have to use a condition in the block. But it seems this is not the solution : so I'll use a Package Manager to listen to packages addition/removal.
I'm also thinking of using a coroutine which periodically updates the state
storeEngines
with a call to
enginesUtils.getMyStoreEnginesNames()
.
i
I don't think you've explained any use cases that would require a polling based approach, I would not suggest going down that dead end when you know what you should actually be doing (only changing the state when something has actually changed)
l
I understand. The first list should be updated in two cases : โ€ข at least one chess oex package is added from Google Play : so that each new package may make one or several new engines available โ€ข at least one chess oex package is removed from Google Play : the other way around I agree that, for these data, a simple polling can't be efficient (unless I poll regularly from a background thread). For the second lists, things are more simple : only this engines page is responsible for the those internal files.
i
If you look at the code I posted, there's a third case as well - the package was replaced (i.e., updated) and you need to refresh the set of engines from the updated app
๐Ÿ‘ 1
l
Right, thanks. So I'm studying the
PackageManager.queryIntentActivities()
in order to handle this loading (and the installation into the internal folder) properly. https://developer.android.com/reference/android/content/pm/PackageManager#queryIntentActivities(android.content.Intent,%20int)
Hi again ! Given a method
Copy code
fun getAvailableEngines(context: Context): Flow<List<ChessEngine>> = callbackFlow {
...
}
Is it then safe to include a call to
getAvailableEngines()
in a saveable state ?
Copy code
var storeEngines by remember { mutableStateOf(getAvailableEngines(currentContext)) }
i
You would never need to do this, just
collectAsState()
your Flow
๐Ÿ‘ 1
l
It works nicely ! Thank you very much ๐Ÿ™‚
๐ŸŽ‰ 1