I have a scenario where I need to send a status back to the starting activity, like we did with startActivityForResult but the current stack is a little different.
This means I have a scenario like this:
ActivityA is using NavGraph, on ModuleX and knows about ModuleY.
ActivityB is using NavHost, on ModuleY.
How would I send information back from ActivityB to ActivityA in this scenario?
If they were using the same NavGraph I could just add an observer to the navController.currentEntry and send it through navController.previousBackEntry.
The issue is, because it's moving from NavGraph to NavHost it means there's no knowledge of the previous graph and because it's between modules I can't even do findNavController(viewId) from ActivityB doesn't know about ActivityA's NavHostView.
SharedViewModels would probably not work either, because both the Activity and NavGraph have changed.
I feel like going back to startActivityForResult might be the only solution here.
Related
I've been struggling with this problem for like a week, it's basically a Backstack problem I didn't found an optimal solution yet. I am working on a project which's flow is like this:
Activity (Fragment_A -> Fragment_B -> Fragment_C -> Fragment_A)
I am setting on Fragment_A one DatePicker and a TimePicker and I have 2 TextViews that redirect the user to Fragment_B. From Fragment_B I send some data to Fragment_C that converts the data and sends it back to Fragment_A.
The problem is that as far as I've understood is that when going back to Fragment_A it goes with a new instance, not the old, so my data there is lost. I resolved for now with sharedPreferences but it seems too complicated for a solution. I've tried with custom beginTransaction() and Navigation component but it didn't turn out well.
I was close, and when going from Fragment_C to Fragment_A there was the new instance on top of the old and at onBackPressed it popped the new instance, and showed me the old but how can I resolve so I won't need to press the back button? I tried to send a Boolean so if it's a new instance pop it, but it popped the old one I guess, because when I pressed back, it just quit the Activity instead of popping the new one.
Any help is appreciated!
An Activity-scoped ViewModel will make sharing data between child Fragments easier. Your Fragments observe the data in the ViewModel, so you don't even have to worry about passing data around. And with Navigation Component, you can use popUpTo and popUpToInclusive to pop Fragments B and C off the back stack, leaving just Fragment A.
If you're not familiar with these concepts, this free course covers them all wonderfully:
https://www.udacity.com/course/developing-android-apps-with-kotlin--ud9012
The two screens relevant to my issue amount to MainFragment (a master view) and ProfileFragment (a detail view). The launch path from login -> main -> profile works fine. The return path isn't working as well. I get stranded at main when navigating backward with via gesture or device button.
On the initial "back" from the profile, I'm returned to main and see main's onViewCreated, onResume lifecycles. I expect back from main would return to login or even exit the app, but instead it reloads main a dozen times before crashing.
For any subsequent "back" from main, the logs reveal main's onAttach, onCreate, onViewCreated, onResume lifecycles recurring each time. This seems suspicious although it's a pretty vanilla navigation graph, a single Activity hosting four basic Fragments. They're all navigated with basic actions using their generated, type-safe Directions classes. I haven't overridden onBackPressed in any of these classes.
Combinations of app:popUpTo="#+id/loginFragment" and/or app:popUpToInclusive="true" haven't helped.
Do I need to implement back or "up" in order to work as expected? Any thoughts are appreciated.
On closer inspection, it's working the way it's coded. Of course it is!
The preceding LoginFragment checks a SharedPreference value and navigates to main. I confirmed that happens so quickly I thought I never returned to login screen, when in fact I did.
I'll investigate removing login screen from the stack after authentication.
I have three activities A, B and C.
A --> B --> C. activity B isn't shown to the user, its calling an api and gathering some information. Should the user hit back I'm hoping for it to go back to A, but not sure how this can be done?
I've already tried coroutines to get around this issue and I've not had much look.
Result is that the back button when pressed continues back to activity C and never gets back to activity A.
Any advice would be great.
Thanks
You can call finish() on B Activity after startActivity(...) call
startActivity(Intent(this, C::class.java))
this.finish()
Why are you using Activity B at all? I think there is a problem with your design. Look into android architecture components project for a good design guideline. Usually things like api calls need to be done inside classes that do not depend on Activity lifecycle, unless you need the activity lifecycle for your requirement. Android Architecture Components "JetPack"
I'm currently using Android Navigation Architecture in my project. It has a feature that can launch any fragment with a shortcut.
Suppose my navigation graph looks like this: A->B->C->D.
When I'm at fragment A , I directly navigate to fragment D with NavController.navigate(R.id.fragment_d). But when I'm press back button, it returns to fragment A. Is there any way to let the destination navigate back to its parent in navigation graph? (I mean, in this case, D back to C, B then back to A).
Thanks in advance.
Generally, you should always avoid creating a synthetic back stack when within your own app (and only do this when launching your app from a deep link outside your app, i.e., via an app shortcut).
However, you can approach this in one of two ways:
If you're okay with resetting the state on A, you can use NavDeepLinkBuilder to construct a set of Intents suitable for restarting your task on the chosen destination:
navController.createDeepLink()
.setDestination(R.id.destination_d)
.createTaskStackBuilder()
.startActivites()
Just call navigate() multiple times.
navController.navigate(R.id.destination_b)
navController.navigate(R.id.destination_c)
navController.navigate(R.id.destination_d)
I think you should be able to use navControler.navigateUp() on the destination if you have correctly introduced the parent fragment for your fragments. Also, consider the difference between the device back button and up back-arrow to go up to the parent
I have a MainActivity with a container FrameLayout in which I change multiple Fragments (Fragment A, Fragment B etc).
In one of this fragments let's say Fragment A I have to open another activity (Activity X).
The problem is that from this activity when I press a button I have to change Fragment A with Fragment B (in the background somehow) and after that, slideout Activity X (with translate animation), and slidein Fragment B ,all this without restarting the MainActivity because I have to keep the state.
How can I do this?
Thanks
Android uses loosely coupled components as its main building blocks. As you know, Activities are one of the main Android building blocks. Thus, interacting between activities are very restricted to a few ways.
Passing data via Intents by startActivity(), startActivityForResult() etc. This way is useful whenever you are starting new activities.
Sending broadcast Intents. This could be useful once you want to send a signal to your another app's component.
Utilizing shared Application object.
Java static fields and some other ways.
In your case I would recommend you to use a Dialog Fragment instead of your second activity, if your second activity is just a login activity or something like that.
UPDATE #1:
If you really would like to keep your second activity, so I would personally recommend using local broadcast mechanism.
Also there are another way to get this done. You could start your second activity as startActivityForResult and then whenever user gets back from your second activity to your first one, your first activity can get informed by its onActivityResult method. There you could switch those fragments.