How Are Android Activities Handled with Jetpack Compose and Compose Navigation

How are Android activities handled with Jetpack Compose and Compose Navigation?

The Compose application is designed to be used in a single-activity architecture with no fragments.

You can still have multiple activities or fragments and use setContent in each of them, but in this case the transfer of data between activities falls on your shoulders. Use this approach if you're adding new Compose screens to an existing application built the old way.

But with Compose, it's much easier to do all the navigation within a single activity using Compose Navigation. Much less code, better performance due to no unnecessary code layers, easy to transfer data, etc.

To work with the view lifecycle, check out compose side-effects:

  1. LaunchedEffect can be used to execute an action when the view appears. It also runs on a coroutine context that is bound to the current composable: you can easily run suspend functions, and when the view disappears from view hierarchy - the coroutine will be canceled.
  2. DisposableEffect can be used to subscribe to/unsubscribe from callbacks.

When you rotate the screen, all effects will restart no matter which key you passed.

@Composable
fun MainScreen(navController: NavController) {
LaunchedEffect(Unit) {
println("LaunchedEffect: entered main")
var i = 0
// Just an example of coroutines usage
// don't use this way to track screen disappearance
// DisposableEffect is better for this
try {
while (true) {
delay(1000)
println("LaunchedEffect: ${i++} sec passed")
}
} catch (cancel: CancellationException) {
println("LaunchedEffect: job cancelled")
}
}
DisposableEffect(Unit) {
println("DisposableEffect: entered main")
onDispose {
println("DisposableEffect: exited main")
}
}
}

Also note that in both cases, and in many other cases in compose, you pass key to these functions. This helps compose understand when the value should be recomputed. In my example it is Unit, which means that it won't change until the view is gone. But if you create a remember value, use another dynamic value from the view model, or pass another argument to composable, you can pass it as a key, this will cancel the current LaunchedEffect job and call onDispose for DisposableEffect, and your job will be restarted with the updated key value. You can pass as many keys as you want.

Read more about the state in Compose in documentation.

Jetpack Compose activities and composables for large projects

It is not a particularly bad practice to make your app multi-activity-embedded, but the thing is -- In most of the cases, you do not need it. The users do not know what an activity is, since they simply look at the app in terms of the screens that the app offers. Therein lies the explanation. A single Composable can represent an entire screen super-easily, it's barely an inconvenience.

HENCE, the entire idea and need of multiple activities gets destroyed. Single activity apps are more efficient too, since there's only one activity so you do not have to explicitly handle the data-flow between various activities. This means a single ViewModel, minimal coupling, high code-readability, and easy data-flow.

This is the same reason that fragments are discouraged too. They often involve multiple viewModels which complicates things. When a Composable can accomplish everything on its own, it automatically becomes the best choice for developers to use to build screens. I would highly recommend, no matter the size of your project, that you stick to a single activity.

I can understand your viewpoint as well, and I have something to help.

The Navigation Codelab clearly and simply explains the Navigation System in Compose, which is a framework that basically allows you to create multiple screen-representing (or other) Composables, and then navigate to and from them from anywhere IN THE OS! It is actually super-easy to use, barely an inconvenience.

Jetpack Compose, using new Activity or new Navigation?

Jetpack Compose is built for single activity architecture what that means is you only have one activity and use compose navigation for navigating in your apps it is much easier also but if you need to use multiple activities you can but the data passing falls on your hands you need to take care of it.

How to handle navigation in Jetpack Compose?

New Jetpack lib has published for Compose navigation. It is still in alpha.

In this new library, now user can able to navigation between different composables with navigation components features.

Using navigation-compose:

dependencies {
def nav_compose_version = "1.0.0-alpha01"
implementation "androidx.navigation:navigation-compose:$nav_compose_version"
}

Example:

Step 1: create a NavController by using the rememberNavController() method in your composable: Link:

val navController = rememberNavController()

Step 2: Creating the NavHost requires the NavController previously created via rememberNavController() and the route of the starting destination of your graph:Link.

NavHost(navController, startDestination = "profile") {
composable("profile") { Profile(...) }
composable("friendslist") { FriendsList(...) }
...
}

Step 3: To navigate to a composable use navigate():

fun Profile(navController: NavController) {
...
Button(onClick = { navController.navigate("friends") }) {
Text(text = "Navigate next")
}
...
}

check more https://developer.android.com/jetpack/compose/navigation

Jetpack Navigation Component with Jetpack Compose compatible?

Long-term, there will be first-class support in the Navigation component for Jetpack Compose. Google has indicated this on several occasions, mostly in the Kotlinlang Slack #compose channel.

Right now (30 June 2020), Navigation knows nothing about Compose. Eventually, my guess is that the Navigation DSL will support referencing composables (or lambdas that update states), but that is just a guess.

If you want to use both today, one option would be to continue using fragments:

  • Have Compose define the UI for those fragments
  • Have Navigation route between the fragments

Later, when Navigation directly supports Compose, you could "unwind" those fragments and do everything directly in Compose+Navigation.

Alternatively, there are non-Navigation routing options available from third parties (though, like Compose, they are all fairly new).

Use NavHostFragment in Jetpack Compose

You are correct that you cannot use rememberNavController() - that will create a completely new nested NavController suitable only for composable destinations.

As per the testing guide, it is strongly recommended to avoid any direct references to any NavController within any of your composables themselves (i.e., a HomeScreen composable). Instead, the recommendation is to pass in a lambda that your composable can trigger when it wants to navigate.

Your Fragment (the one calling setContent on your ComposeView) would then be responsible for implementing that lambda and calling NavHostFragment.findNavController(this).navigate(directionToFragment2).

As a (less recommended) alternative, you can also use LocalView.current.findNavController() as Fragments populate the NavController at the view level as well and LocalView points to the ComposeView hosting your Composable.



Related Topics



Leave a reply



Submit