olshevski / compose-navigation-reimagined

🌈 Type-safe navigation library for Jetpack Compose
https://olshevski.github.io/compose-navigation-reimagined/
MIT License
534 stars 18 forks source link

How to provide function #14

Closed T8RIN closed 1 year ago

T8RIN commented 1 year ago

When i provide function or something that cannot be parcelized it becomes lost when the application kills the system, what should i do?

olshevski commented 1 year ago

@T8RIN Sorry, I do not understand what exactly you mean. Can you provide an explanation or an example?

T8RIN commented 1 year ago

@olshevski

     @Parcelize 
     class Exit( 
         @IgnoredOnParcel val onExit: () -> Unit = {} 
     ) : Dialog()

    BackHandler { 
         dialogController.show(Dialog.Exit(onExit = { this?.finishAffinity() })) 
     }

    DialogNavHost(controller = controller) { dialog -> 
         when (dialog) { 
             is Dialog.Exit -> { 
                 ExitDialog(onExit = dialog.onExit) 
             }
         }
     }

Something like this, i cannot parcel function, so i added IgnoredOnParcel annotation

olshevski commented 1 year ago

@T8RIN You are doing something very tricky here 😀

Why don't you want just to set onExit listener inside DialogNavHost:

@Parcelize 
     object Exit : Dialog()

    BackHandler { 
         dialogController.show(Dialog.Exit) 
     }

    val activity = LocalContext.current as Activity
    DialogNavHost(controller = controller) { dialog -> 
         when (dialog) { 
             is Dialog.Exit -> { 
                 ExitDialog(onExit = { activity.finishAffinity() }) 
             }
         }
     }

Something like this.

T8RIN commented 1 year ago

@T8RIN in this case it is possible, but when there are comes callback functions i cant just do that in nav host

olshevski commented 1 year ago

@T8RIN Ok, I've looked through your code in the app and I see what you are doing.

Unfortunately, there is no way to serialize functions, because it is not data.

I wonder, why do you need DialogNavHost in your code in the first place? Do you switch between these dialogs anywhere in the app? It seems to me that it would be much easier to define simple composable dialogs in the place of use, thus the callback could be defined there. And if you have a set of dialogs that should be switched between, I also suggest you to define a smaller local DialogNavHosts with all callbacks defined in the place of use.

If it is not an option to you, and you really need to keep all dialogs in a single place, you could potentially think about some shared data holder + event dispatcher. But it will make things even more complicated.

T8RIN commented 1 year ago

@olshevski i did this in thoughts of making app more structured, to shift the call of dialogs to another element, function transfer works, even with repeated screen rotation or other global recompositions, but when not in the application for a long time, it is erased. will it be ok if i create a viewmodel to save this?

olshevski commented 1 year ago

@T8RIN No, do not rely on view models. The whole process together with ViewModels may be destroyed and recreated later. Your callbacks however will be reset to the default ones {} in this case.

Try to rethink what you are actually doing here. If you still want to go on with your current structure you need to decouple dialogs and screens that are awaiting callbacks. It could be done with some kind of events shooting from DialogHost through some channel/event bus and being consumed by each screen.

T8RIN commented 1 year ago

Thanks for your answer!