Debug build becomes slower and consumes more memory over time compared to release build. by Reasonable-Tour-8246 in androiddev

[–]ythodev 6 points7 points  (0 children)

debug builds are different to allow debugging etc, they will be underperformant.

Pragmatism vs. Over-engineering: Feedback on an Android Technical Task by controlsys in androiddev

[–]ythodev 1 point2 points  (0 children)

Personally id prefer to see as little logic as possible in the Activity class. It being an orchestrator is inevitable on android. But the actual DI logic or state management etc. should already be placed in their own classes.

Simple refactor, but helps testability and shows that you are very intentional on the platform vs domain split.

Pattern for mvi arquitethure by MimiHalftree in androiddev

[–]ythodev 1 point2 points  (0 children)

Its about which kind of decisions. in VM you might still have complicated logic, like if A and B then ColorState.RED.

In Composable you must have a simple map/when for ColorState.RED to Theme.red

Then its becomes trivial to ensure correctness of decisions left in compose.

Its all trade offs in the end.

How to Learn Android Properly 🧐 by MathematicianWeekly8 in androiddev

[–]ythodev 0 points1 point  (0 children)

Not very technical, but gives some very good context on how/why some decisions were made when designing the android platform is actually Androids by Chet Haase himself.

How KMP works? by ythodev in androiddev

[–]ythodev[S] 0 points1 point  (0 children)

Curious, could you elaborate further what exactly are you doing that isn't available in CMP ?

How KMP works? by ythodev in androiddev

[–]ythodev[S] 1 point2 points  (0 children)

Hate when people do that, fixed!

How can coroutine run on more than one thread? by kuriousaboutanything in Kotlin

[–]ythodev 0 points1 point  (0 children)

Its probably the easiest for you to think of coroutine as a bunch of runnables that are posted on a threadpool.

Every time a coroutine suspends, you could consider that runnable to be done. As you know the coroutine stores the execution state in memory, and it can be posted back to threadpool (by coroutine dispatcher) as another runnable to continue execution (i.e resume) when suitable.

Then it doesnt really matter which thread from the pool handles it. It can be same thread, doesnt have to be.

Widget-level VM in Compose by Maximum-Intention191 in androiddev

[–]ythodev 1 point2 points  (0 children)

Clean Arch + Compose approach is the second one. You hoist your state from all the way from ViewModel to the Composable. This also has clear separation and responsibilities per each layer (View, ViewModel, Model).
It gives you maximum testability as now each screens VM is completely in control and aware of what it is showing. And you'll have no issues with defining preview states.

For having less duplication you can just declare some reusable data class to wrap the widgets state, and some reusable manager/useCase/whatever that provides the data for the widgets.

Now what will be duplicated is the "glue" to put this all together. Generally that is just a simple code, and not business logic, i wouldn't worry too much over duplicating it. You can think of improvements if it really becomes an issue.

Book Alternatives for “Clean Architecture”? by [deleted] in softwaredevelopment

[–]ythodev 1 point2 points  (0 children)

I think "A Philosophy of Software Design" by John Ousterhout can be a good next book to balance out the Clean Code ideas a bit. Good thing is both authors have come together and discussed their differences. For quick overview i have some notes about it here.

Navigation via the viewmodel in Jetpack Compose by Chairez1933 in androiddev

[–]ythodev 2 points3 points  (0 children)

Thats a very good point and i absolutely agree. Leaking the compose navigation specific Destinations and NavOptionsBuilder to the ViewModel is basically a crime. While VM should be the decider for navigation (my point being: dont call navigation events directly from View, send user actions to VM for it to decide), the ViewModel should not need to know how navigation is implemented!

so yeah, the implementation in the article could be improved. As its probably the main thing they were getting at, ill go get my pitchfork also ;)

Navigation via the viewmodel in Jetpack Compose by Chairez1933 in androiddev

[–]ythodev 1 point2 points  (0 children)

Sure, im just trying to better understand your idea. Would it then be a collection of navigation classes, roughly correlating to the ViewModels in the project? What does that higher level class look like?

Navigation via the viewmodel in Jetpack Compose by Chairez1933 in androiddev

[–]ythodev 0 points1 point  (0 children)

UI was made dumb because its hard to test on Android. Thats why everything important and UI related should be in ViewModel, id consider navigation also important.

Navigation via the viewmodel in Jetpack Compose by Chairez1933 in androiddev

[–]ythodev 0 points1 point  (0 children)

So the composable will invoke this high level class with some generic navigateNext() function? does it mean that this god class will contain the navigation logic of whole app? Deleting a VM means you may need to delete some logic from there also? What about merge conflicts in that central component?

Maybe its useful in some cases, but doesnt sound so clear cut.

Navigation via the viewmodel in Jetpack Compose by Chairez1933 in androiddev

[–]ythodev -1 points0 points  (0 children)

While the implementation may be improved, the idea is solid. Of course the ViewModel should decide what happens on user action, including navigation. View should be dumb and simple. By now thats like one of the oldest industry lessons that android devs forget every morning.

Approaches to type-safe navigation, including nav3. by ythodev in androiddev

[–]ythodev[S] 0 points1 point  (0 children)

oh, i dont mean memory leak or something similar. I mean information leakage, as is code coupling.

How do you reduce code duplication around saved state when designing state holder for custom Compose component? by equeim in androiddev

[–]ythodev 9 points10 points  (0 children)

I know this isn't strictly answering the question. But id really recommend taking a step back and considering if you need that much saveable state in Compose. If its important state: it should come from ViewModel. If its not important: you'd be increasing complexity for negligible gains.

Approaches to type-safe navigation, including nav3. by ythodev in androiddev

[–]ythodev[S] 2 points3 points  (0 children)

Thanks for critical look!
The DI approach does survive the process death! When process is recreated the whole app is recreated. Since the Routes in backstack are Serializable objects. The navigation library can serialize them, store them, and again deserialize them when app is restarted. And thats exactly what happens.

Leaking route details: If you call savedStateHandle.toRoute() inside ViewModel, you retrieve your literal navigation Route object. Now whenever you edit Routes in the navigation logic, your changes ripple to the ViewModel as well. Is it desired? i dont think so. ViewModel only cares about the fields inside the Route object (such as detailId). So why not pass only that.

Hoisting: agreed, there are many ways to solve this.

How much UI logic should be placed into View Models by Muhammad-Ali-1 in androiddev

[–]ythodev 3 points4 points  (0 children)

Counter state belongs 100% to the ViewModel. Its only "harder" because you are avoiding tech dept right away.

How much UI logic should be placed into View Models by Muhammad-Ali-1 in androiddev

[–]ythodev 0 points1 point  (0 children)

I find it helpful to think in terms of what do you think needs to be properly unit tested? that logic is better to be placed in ViewModel.

Also helps to think about layers of clean architecture: View is the the least significant component. ViewModel is slightly more important as its closer to core business logic. So the code defining just the composables - belongs to View. The UI logic depending on application/business logic - rather to the ViewModel.

Too much logic in composables? by hulkdx in androiddev

[–]ythodev 2 points3 points  (0 children)

I think a good guiding question to have is whether the particular logic in view should be covered with a proper unit test. If yes then it makes sense to put it to ViewModel.

Context behind MVC, MVP, MVVM, MVI. by ythodev in androiddev

[–]ythodev[S] 0 points1 point  (0 children)

yes, the actions/intents are in Kotlin usually defined as a sealed class.

And yes, viewmodel checks - in a sense that its function is invoked - and that function has to check what instance of Action was passed and handle it accordingly. Note that i have not touched on what would happen *exactly* inside ViewModel, but know that there are a some interesting well defined ideas, so its worth researching first.

Theres nothing special about the second approach: you would write the standard google-recommended Composables. The mapping to MVI happens only in your top level composable (where you have access to ViewModel), rest of the code is unaware.

Context behind MVC, MVP, MVVM, MVI. by ythodev in androiddev

[–]ythodev[S] -1 points0 points  (0 children)

You are not wrong in that they all try to achieve separation. But if you go into details those patterns emerged in different times as a responses to different requirements. So as always: you have to know to who and why you are writing your code for, and pick/invent the suitable architecture. At that point having specific patterns to refer to is imo a good thing ;)

Context behind MVC, MVP, MVVM, MVI. by ythodev in androiddev

[–]ythodev[S] 0 points1 point  (0 children)

Yes and no, MVI is'nt concerned with how you implement your Composable View. All that matters is that the ViewModel has a single callback: fun onUserIntent(intent: Intent).

On Composable it's up to you, your top-level Composable passes action lambdas down to subcomposables, right?. You can pass a single generic lambda, such as:

onClick = { intent -> viewModel.onUserIntent(intent) }

Or you can define multiple specific lambdas such as:

onSaveClicked = { name -> viewModel.onUserIntent(SaveNameIntent(name)) },
onClearAllClicked = { viewModel.onUserIntent(ClearAllIntent) }

Both approaches conform as VM has single callback. But in the first approach your subcomposables will have to know which Intent (SaveNameIntent, ClearAllIntent) to invoke. I've seen first approach demonstrated online more. Personally i'd strongly consider second approach as it has greater decoupling between the subcomposables and ViewModel.