Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Nav scoped view models#817

Merged
twizmwazin merged 9 commits into
LemmyNet:mainfrom
nahwneeth:scoped-view-models
Jun 26, 2023
Merged

Nav scoped view models#817
twizmwazin merged 9 commits into
LemmyNet:mainfrom
nahwneeth:scoped-view-models

Conversation

@nahwneeth

@nahwneeth nahwneeth commented Jun 22, 2023

Copy link
Copy Markdown
Contributor

Since PR #765 was too big, splitting it up into multiple PR to make it easier to review.

Scoped view models

  • All the view models that were declared in the activity are now scoped to the routes in which they are used. View models used by most of the routes (like SiteViewModel, AccountViewModel & AccountSettingsViewModel) are left untouched.
  • This prevents sharing view models that lead to stale data & reloading the data when navigating back.
  • Making the LaunchedEffect run only once per route. This helps ensure that the content isn't reset with new data when moving back from one route to another. Things like scroll position & filters are also retained.
  • Using extension function on navController to navigate in a type safe manner.

Closes #704
Closes #402
Closes #774
Closes #835


The following is the existing design where the view models reside in the MainActivity and are passed to all the activities:
Untitled Diagram-Existing drawio


The following is the design implemented by the PR:
Untitled Diagram-PR drawio

  • The channel is also a ViewModel that is scoped to the NavHost's nav graph which has route = Route.Graph.ROOT. This is created on the fly whenever you see something like transferPostEditDepsViaRoot = navController.rootChannel<PostEditDeps>().
  • Instead of initializing a global viewmodel and then navigating to it's activity. We store the dependencies in the global channel and then initialize the view model in it's respective activity.
  • On success the updated data is put to the parent's back stack entry with a specific key (PostEditReturn.POST_VIEW) and then navigate back. On navigating back, the parent will recompose and we check if a value has been set in PostEditReturn.POST_VEW and update the post accordingly.

Other Notes:

  • I've provided extensions to navigate to each activity. For eg. to navigate to PostEditActivity on has to call navController.toPostEdit(Channel<PostView>, PostView). This way it's a compile time error to forget providing the dependencies necessary to initialize an activity.
  • These deps are converted to JSON and rememberSaved in the respective route (when navController.takeDepsFromRoot<PostView>() is called). The updated data on the back stack entry's SavedStateHandle is also in JSON. Both survive process death.
  • To reuse code, I've introduced abstractions like InitializeRoute and ConsumeResult which are self-explanatory.

@nahwneeth

nahwneeth commented Jun 22, 2023

Copy link
Copy Markdown
Contributor Author

@marcellogalhardo

I've updated the code to survive process death. Would appreciate if you also reviewed this. I've taken your previous feedback into consideration and creating view models on the fly, using extension functions for navigation and moved the initialized variable into the view model. The dependencies are converted to Json and being rememberSaved.

For people willing to test this branch (& for my future ref):

  • Go to any view/screen. Click on posts & profiles & communities any number of time in a sequence.
  • Click on home button / swipe home.
  • To kill the process do:
    ./adb shell am kill com.jerboa.debug
  • Open the app again from recents and the app should continue from where you left off.

@dessalines

Copy link
Copy Markdown
Member

It might be a while till I can go over bigger refactors like this.

@twizmwazin twizmwazin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would love to get this merged once rebased

@nahwneeth nahwneeth marked this pull request as draft June 26, 2023 03:30
@nahwneeth nahwneeth force-pushed the scoped-view-models branch from b614511 to d99a123 Compare June 26, 2023 03:45
@nahwneeth nahwneeth marked this pull request as ready for review June 26, 2023 03:45
@nahwneeth

nahwneeth commented Jun 26, 2023

Copy link
Copy Markdown
Contributor Author

Note regarding changes made while resolving merge conflicts:

  • The user preferred sort & listing defaults were housed in HomeViewModel (PR Fix default sort and listing type to read from db #854). This has been moved to SiteViewModel. Reason: The CommunityActivity depended on HomeViewModel for the defaults which hinders scoping. Since, both already depended on SiteViewModel it made more sense to keep them there. Also, changing the filters in HomeActivity doesn't overwrite the user defaults. Would appreciate if @beatgammit reviewed these changes and pointed out if I missed out or overwrote any fixes.
  • The PostCreate & PostEdit were consolidated (PR Consolidate composables for CreatePost and PostEdit #860). I've tested the post edit and create functionality after rebasing and they seem to be working. Would appreciate if @sockenklaus reviewed these changes & gave a thumbs up.

Comment thread app/src/main/java/com/jerboa/MainActivity.kt
Comment thread app/src/main/java/com/jerboa/ui/components/post/create/CreatePost.kt Outdated
Comment thread app/src/main/java/com/jerboa/ui/components/home/HomeActivity.kt Outdated
Comment thread app/src/main/java/com/jerboa/MainActivity.kt
@sockenklaus

Copy link
Copy Markdown

Would appreciate if @sockenklaus reviewed these changes gave a thumbs up.

I'll gladly do and give it a look tonight.

@nahwneeth

Copy link
Copy Markdown
Contributor Author

I've opened a new issue for the filters #886. For now, I've pushed a commit to ensure that the filters (in home & community activity) are read form the account variable. Ig we can continue with merging this PR and take up the filters thing separately. Any other issues with this branch, do let me know.

@sockenklaus sockenklaus left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only reviewed the files regarding post creation and editing because I honestly can't wrap around my head about that amount of abstraction you added without investing a serious amount of time which I just don't have atm. (Hence my rather small PRs)
What I reviewed looked correct though and post creation and editing acted as expected.

@nahwneeth

nahwneeth commented Jun 26, 2023

Copy link
Copy Markdown
Contributor Author

What I reviewed looked correct though and post creation and editing acted as expected.

Thanks a lot for taking the time! Will make the changes you requested.

I think that's the hard part, reviewing changes. I'll try to document these changes better.

@sockenklaus

Copy link
Copy Markdown

I think that's the hard part, reviewing changes. I'll try to document these changes better.

Thank you for further describing the changes you've made. I really appreciate your effort to make these changes as understandable as possible. 🙂

@MV-GH

MV-GH commented Sep 1, 2023

Copy link
Copy Markdown
Collaborator

I have question regarding initializeRoute, why did you take this approach over just having the necessary fields passed to the constructor of the ViewModel. Passing it in the constructor is much more typesafe as we now don't have to set each field as nullable that we have to check constantly

@nahwneeth

nahwneeth commented Sep 1, 2023 via email

Copy link
Copy Markdown
Contributor Author

@MV-GH

MV-GH commented Sep 1, 2023

Copy link
Copy Markdown
Collaborator

Thanks for your quick response, I'll make a issue for that and work on refactoring that

@MV-GH

MV-GH commented Sep 1, 2023

Copy link
Copy Markdown
Collaborator

I do have another question,

For communityViewmodel you did this

val communityViewModel: CommunityViewModel = viewModel(
   remember(it) { navController.getBackStackEntry(Route.Graph.COMMUNITY) },
)

I am not sure what this does or why it exists?

Why can it not be embedded in CommunityAcitivity?

@nahwneeth

nahwneeth commented Sep 1, 2023 via email

Copy link
Copy Markdown
Contributor Author

@MV-GH

MV-GH commented Sep 1, 2023

Copy link
Copy Markdown
Collaborator

Hmm I see but I am thinking of simplifying this by just passing the CommunityView into Sidebar using the addReturn. Would a separate community_graph still be needed then?

@nahwneeth

nahwneeth commented Sep 1, 2023 via email

Copy link
Copy Markdown
Contributor Author

@MV-GH

MV-GH commented Sep 1, 2023

Copy link
Copy Markdown
Collaborator

Alright got it working, had to make a reverse addReturn/consumeReturn

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

5 participants