Should You Use a Navigation Library in Jetpack Compose?
HTML-код
- Опубликовано: 29 сен 2024
- In this video you will learn if you should use a Navigation Library in Jetpack Compose.
💻 Let me be your mentor and become an industry-ready Android developer in 10 weeks:
pl-coding.com/...
⭐ Courses with real-life practices
⭐ Save countless hours of time
⭐ 100% money back guarantee for 30 days
⭐ Become a professional Android developer now:
pl-coding.com/...
Get my FREE PDF about 20 things you should never do in Jetpack Compose:
pl-coding.com/...
Regular programming advice on my Instagram page: / _philipplackner_
/ _philipplackner_
Join my Discord server:
/ discord
Yeah. It feels like Navigation library by google is built by a web developer 😂
One of the Compose's og author is a also the og author of React. FunFactIfYouDon'tKnow.
Also it so hard to maintain the routes.
As i’m working on a multi module app and it violates single responsibility principle :(
Absolutely 😂. It's really annoying
Deep links come from web browser so it makes sense... :/
When compose first came out I thought they were just ripping react/flutter, which I found disappointing at first. But now I appreciate that you see similar standards for different frameworks
Compose navigation might be complex, but the official documentation is very helpful. I'll choose the official one over the others.
In my humble experience passing complex objects directly between screens in navigation can lead to issues like increased memory usage, tight coupling, and serialization challenges. It's generally better to pass only minimal data, like IDs, and then retrieve the full objects in each screen independently. This approach enhances modularity, makes your code easier to maintain, and is more efficient for memory management. Sharing ViewModels between screens isn't always ideal, as it can create unnecessary dependencies. Instead, fetching data independently in each screen or composable based on passed identifiers keeps components decoupled and your app's architecture clean and scalable.
Exactly that's my point
right
This has its own tradeoffs. First of all, loading everything from scratch on every new screen is not free it comes at a cost. Either you're fetching from the network, and introducing extra delay for an object or data you already have. Or you are fetching from the DB, which has an extra overhead in setting up tables and what not. If you're using a local DB, you also have to worry about syncing and making sure you have up to date information. You also have to maintain this DB/tables and do migrations if things change in the future.
@@isaac48 yes, but high coupling is one of the worst technical debt you can add to your codebase, besides you can always have an in-memory cache making it just as performance as passing the object.
@@isaac48 i mean, if you pass objects trough navigation you also have to worry about syncing... " extra overhead in setting up tables" is literally 10 minutes of work, you already have plugins that convert your responses to db classes, but you could easily make your own. "You also have to maintain this DB/tables and do migrations if things change in the future", kotlin realm does most of the stuff via auto migrations, for some specific stuff its easy to write it. i just dont see the advantage of passing objects between screen, its anti pattern, it offers no benefits over sending ids, like data syncing and reducing api calls, not true, if you are on the screen for 30 mins then tap on listing item to navigate to details you still have to call api when you land on details page to ensure latest data is shown if its prone to change, if it isnt you wont be calling api even if you send id, and like stated before me, coupling will kill your code. also you dont even need database, you can just use the new datastore that supports kotlin flows for this data caching.
Let's be honest. Google gives us a lot of great helpful tools to build an android project. However Google sucks really hard at implementing navigation. Both navigation for compose and on fragments are bad, have a lot of boiler plate, you need to draw arrows like a painter to know which fragment navigates to which. Like... why?? I just want to navigate from fragment A to B, why can't i do it inside the code?
So my personnal experience is to screw google navigation. It's bad. If you want navigation purely in compose just go for voyager appyx etc. if one library dies, the transition isn't as bad as you may think. If you think that won't be easy in larger project then you should know that for that case you will have multi module helper which will be just a coverage for the navigation library. Then the transition will be smooth and easy.
But there is another but. I've experienced a lag issue navigating purely in compose. When you navigate from screen A to screen B, and screen B will change state during the transition (loading -> data), and the data will be list of images that you need to display then on slower devices you will experience frame drop. It won't happen if you use fragment navigation, so that's why for now i recommend using compose with fragment navigation like FragNav or Enro. Enro looks really nice, but if you have to transition between main and nested navigation often then i do not recommend it.
I would recommend option 4. Yes, you write lots of fragments, but, it's a compromise and it works well. I've been using it for 2 yrs now, and the project has grown, but, it's not caused too many complications.
Hey. Could you share how you navigating from Composable to xml defined destination?
Answer: no, you shouldnt. Tying yourself to a third party library for such a simple action as navigating is an error. Unless a big company like Square, Facebook, Airbnb etc maintains it officially; then maybe you can start thinking of it. Otherwise, build your custom solution adapted to your project.
Well isn't that good, to just take data from the database instead of passing it through arguments.
It always follows the single source of truth rule
That stores more than need to be stored and makes navigation unnecessarily complex and unintuitive imo
@@PhilippLackner why so? native apps are (more often than not) made with the idea that they should work in offline mode as well, so caching data is inevitable, so this argument doesnt stand. also on the note of passing id vs passing complex objects from screen to screen, never have i ever heard a developer say its better to pass complex object rather than just pass an id and then re-fetch the data from the DB at the destination. you maintain singular source of truth, and i dont rly see what makes the navigation so complex and unintuitive? using jetpack compose navigation for 2 years in production ready apps, never had a single problem with it, nor did i ever had a problem with just passing id as an argument, it doesnt create boilerplate code, it doesnt increase the code complexity, its not unintuitive for new developers.
to each their own i guess.. just dont understand the hate towards the compose nav
@@vickedvuljo yeah you got my point bro
@@vickedvuljo in the case of a simple detail screen where you have the item in the DB anyways, then for sure just pass the ID. Sometimes an app doesn't require an offline caching approach though and all items are fetched from an API. In that case I'd consider it rather unnecessary to reload the item on a detail screen since it fires a network request which comes with multiple downsides (battery drain, connectivity, slowness). And introducing a caching mechanism just for a list/detail navigation seems unnecessary and unintuitive to me as well. Unless your object is huge, passing it as a parcelable doesn't really have any downsides
I have this flow: create/edit -> preview -> upload. It's all done in memory, storing the data in DB only because of the Nav library's limitations sounds bad.
Also, the too-often-used phrase "single source of truth" quickly turns into "source of lies" when you kill the app and the data remains in the DB but it shouldn't.
Yes, in-memory cache solves this particular example. But why do I have to manually implement it, if it's used exclusively for the navigation? It could just as well be part of the library (as is the case with most of the unofficial libraries).
In the company I work for we use a custom solution on top of compose navigation. The main benefit is that when we need a new feature for this library, we just add it and it's ready to go.
Thank you Philipp for the video. I just wanted to bring to your attention that Google has released a detailed guide on achieving type-safe navigation through their library. I think it's a really good approach for most of the projects, even if there's a little bit of boilerplate code to write each time, which does not happen with Compose Destinations for example.
Can you please share the link? Can’t find it
i hate the overuse of libraries ! unless it is supported by google or jetbrains, it would be the last solution i opt to when solving a problem.
Oh man what a timing! I was just bashing my head with navigation on a green field project and I was having all these questions you've nicely put in perspective.
I don't know if it's library, my compose navigation is extremely laggy,,idk if somebody has experienced this,if yes how did you fix it?...I will really appreciate
It's not true that Android is in a typesafe environment. If your app is using fragments (as opposed to only compose), your fragment arguments will be null if you rotate your app.
I totally respect your content and your efforts in android development and programming as a whole.
But please show us more of code than your handsome face speaking.
I just came here to comment that nav compose library is really janky
A guide video on Building a custom navigation system on top of Google Compose Navigation Would be great !
I would pick the custom navigation approach, even though initially it would take quite some time to make it, but having the full ability to customize and tailor the navigation to the project specific needs is the best option in the long run.
Believe Compose Navigation will get better over time ... Google will always support it or provide a migration path to what they build next ..
kotlin multiplatform- Voyager❤😊
You should make a video about store4/store5
It would be great if you could make a video which compares the most popular navigation libraries :D
Google has done a lot of good things with Jetpack. Compose Navigation is definitely not one of them.
Thx for your great video.
After get familiar with compose navigation I met Navigation destinations. I thought that this is it, it will be the finest solution, but longer work with it, I turn more into custom solution.
Hi bro, can u do tinder like swipe animation in jetpack compose please 🙏🙏🙏🙏
Google's compose NavHost and route pattern looks like web server routing. I like this way. But I still dont' know the way that pass data directly on startDestination and receive this data in ViewModel with savedHandle
I think path routing is a deliberate design choice, because this way the routing system becomes inherently compatible with deep links
What library do you recommend? You mentioned different ones, which one is better for not multiplataform ?)
I'd take a wild guess that Philipp would recommend Compose Destinations in that case
I heard about Odyssey library for navigation. But still haven't tried it yet.
Wow, you are reading my mind again! I have been thinking about navigation for the last week!
Is that third party library can handle nested navigation?
voyager can do it in kmp i know
I don't understand the problem, What is so complex about compose navigation?
I use it and it's work super well i din't find any problem.
First thing first, please don't mix OOP Paradigm, and Functional Programming Paradigm. Compose is based on Functional programming "Function Compositions".
I din't find any problem parsing parcel anyway. All i need is just add lambda for "event" in the child function as function composition.
```
ScreenLogin(
val onLoginSuccess: (AuthData) -> Unit
)
```
now what is the problem? want to parse the whole object to the next screen? please don't. it's very bad approach. why would you do that.
But in case you need, you can use Use Lazy evaluation if the object is too big:
val authData = { AuthData(.....) }
Voila, lazy evaluated.
I personally recommend to never tight a function with any context, if possible. Make the function as independent as possible. How ever, we can use custom payload if we want to.
This is my approach on how i specify payload for a function, and make it un-tangled with base context. (By un-tangled i mean we not using Application's Model, because when we do, then the function is tight to the application context. It is not wrong, i just don't recomending it. I prefer make functions as independent as posible.)
```
interface LoginScreen {
@Immutable
data class Payload(
// action
var goBack: () -> Unit = {},
var onLoginSuccess: (user: AuthToken) -> Unit = {},
// context
var firebaseContext: () -> FirebaseContext
)
companion object {
@Composable
operator fun invoke(
payload: Payload
) {
Content(payload)
}
}
}
@Composable
private fun Content(
payload: LoginScreen.Payload
) { ... }
```
note: don't get it wrong. it can "requires" some context, but it's not necessary tangled to the application context. instead, the application should declares all context within that app.
fragment and compose are different.
Its different in it's base principle and paradigm.
Compose use: Functional programming paradigm and Function Composition.
Fragment: Is Java delegation. It's based on OOP. Using reversed dependency, and all that OOP paradigm.
Be careful. They are based on different paradigm, different thinking framework. If we still using OOP thinking framework, well it's very wrong.
My opinion. What ever the library is, the closest with the Theory, is the best. I found that compose navigation is very well close to the theory. what ever happen tomorrow its should not be a problem.
Because when we facing a problem, all we can do is go back to the theory. So as long as the approach is well oriented to the theory, it is good approach and should not be a problem. Because it's deprecation will have no impact to the code sctructure what so ever, (if the approach is match to the theory).
This is example only, not best approach what so ever. But i belive as long as our approach match with the theory, it is best approach.
But isn't compose suppose to be purely presentational? why are people having the urge to replace fragments with it? Its meant to just replace xmls... the idea of making it handle navigation too is conflicting! I thought we preached separation of concerns? and there we go inventing hacks instead of letting it have just one single responsibility
I like your videos but please try to use the previous approach of explaining through diagrams and other presentations, rather than just your face in the whole video. Some of us understand very easy with the diagrams. I don't see the reason why we should see your face for the entire video, it's the same as we just listen to your audios.
Whether fragment navigation supports multiplatform?
You can't use fragments in multiplatform since they are android specific.
One not related question: When I click on Get your free PDF for 20 things not to do in Jetpack Compose, why it is navigating to a payment screen asking for 500+ Euros? o.O
What do you mean compose navigation doesn't support animation of screen sliding out and new screen sliding in? It feels like it was always there, and navigation graph has default animations, and you can override it for each screen....
Hey Philipp, just a tip for your channel: If you could use some good B-roll footage to help communicate the concepts, it might really help the communication. I got lost in the sea of words and struggled to follow, but the video footage explaining it alongside your words would really help. Hope this helps!
I don't know is this the efficient way or not but I personally use viewmodels for passing the complex data betweeen screens , there will be mainviewmodel for the mainactivitiy and every composable screen has it;s own viewmodel . In the navhost we pass the mainviewmodel object and everything works fine for me! . Is there any problem with that ?
You can set custom animations for compose navigation, there are 4 parameters in NavHost or alternatively you have very same 4 parameters for your composable() builders
Guys that have a background on web dev are wondering what's the big deal😅
Great video!
Would like to hear your opinion on Circuit (navigation but also MVI)
Defining and using a navigation viewModel which is bound to the lifecycle of your Activity or NavGraph along with compose Navigation library works in most scenario!
I would love to see a video about sqldelight and some extra components like sqldelight pagination. Im struggling to implement a room like database and pagination that works with compose multiplatform
Any coupon code for your course.?? i just wanted to enroll course.
they already have transitions in google lib
Do you already have video for customer navigation?
Always use a custom navigations
"Build a custom navigation system on top of Compose Navigation" sounds great! Adapting the official library by extracting the boilerplate code into reusable components and tailoring those components to your specific navigation logic is a worthy investment of time and effort for a big project, because this way you can enjoy a navigation system that is maintained by Google and you, and is perfect for your app!
I used Compose Destinations for ~6 months, made a couple of big projects with many screens. It's not that bad (better than from google), but I can't say that it is good either.
So I made my own scalable navigation system, and I can say, that using your own navigation 100 times better, that's not that hard to do, but it is so much better to work with your own navigation.
That's sound greate, can you share some information about your navigation system ?
@@yahussainmazloom1 Well, basically it's a Viewmodel with saved state handle states like backstack, arguments and current screen. Also I made animations between screens. It is not that complicated, the whole file is around 200 hundred lines, but I spent a LOT of time optimizing and making it better, just start with something, over time you will figure how to do it better.
P.s. in terms of performance it is around the same as Compose Destinations, but much more stable(in terms of errors it doesn't throw anything).
@@acclorite_ in compose destination can you pass complex data between screens? Or which approach do you use for this ?
@@AlonaRozlach-ze1rg I can pass complex objects in my Navigation, but only Serializable, so I can save them in Saved State Handle. Though that is not required and can be changed pretty easily. I prefer simple objects, for example IDs, as they take less time to retrieve and save than complex object.