I have 2 Activities A and B. Now these are my objectives.
When I'm in B and if I press the Home button, the state of the Activity should be saved. (No problem with this.)
When I start B from A after step 1 a new instance of B should be created (i.e) Previous state should be discarded.
But in Step 2 the state of B still prevails. How do I accomplish my objective?
I think one possible solution woudl be to pass some extra information inside the starting Intent, when you start Activity B from A (like a boolean value). And in the "onStart()" of B, you check if you can find this extra info in the intent (you get it with getIntent()). If it's not present, that means you do reload the activity's previous state. If it is, then you don't reload it.
refer this url
Android; How can I initialise state in one activity, then have another refresh that?
You don't even need to send a boolean like Scythe suggested. The Bundle savedInstanceState will be null in onCreate for Activity B if Activity A just started it, whereas it will be non-null if you are coming back from a saved state.
Related
Situation:
Starting from my host activityA/fragment A, I click on a button to start host activityB/fragment B. Fragment B is a fragment which enables filtering options for Fragment A. After selecting the options, the user can press the navigate up button to return to fragment A.
Problem:
I would like the state of the options selected to be retained when navigating to Fragment B more than once. Since this is a filtering option, it would be preferable to not save this in storage beyond the duration of the application (It's just filtering. Not necessary to keep the information stored for a long time. Just in between navigation).
Things I've tried:
OnSavedInstanceState - realized that onNavigateUpTo() / finish() don't trigger onSavedInstanceState
android:launchmode="singleTop" - Because the activity is finished and destroyed from the backstack, no instance of the activity is available to receive the new intent.
setRetainInstance - Activity is destroyed so attached fragment also destroyed.
A possible solution I've found is to use setResult and return the values to Fragment A. Then put these values as EXTRAs into a new intent when starting Fragment B again. This solution seems clunky. Is there a cleaner solution that just allows Fragment B to "remember" its state instead of passing values back and forth?
As you have stated the fragment is destroyed when user goes back so there is no way to get the "state" back. Also it does not make sense to store state as logically the fragment/activity is not needed from platform point of view.
So the way to 'remember' the state of fragment is to store the filter data in some other variable(s) and give it back to it when it is re-launched. What you are trying to do it perfectly fine i.e. return the filter data as result and send it back to fragment at re-launch.
To make it simpler you may write a class containing all the filter options and make it Parcelable. You may choose to make it a global so that you may not need to send it across activities, I would not prefer to do that though.
One UX issue is when user presses up/back it is generally expected that user has cancelled the operation. I as a user expect when I press back it cancels the operation and when I press "apply" it applies the filters. You may need to rethink about the user experience about applying filter on back press.
I have two activities A and B. The A has a ListFragment which uses LoaderManager, whereas B activity shows a details about the item selected in the A's ListFragment. I've just noticed that when I use a back button to get from the B back to the A, the position in the ListFragment preserve, but when I use the up button (left-point caret) in the action bar, the A activity is recreated and thus position in list view is lost.
I would like fix this issue, but I am not sure about the best way how to do it right.
I come up with this solutions:
a) Use onBackPressed()
Replace the default implementation for the android.R.id.home (the up action bar button) in the B activity, and instead of the NavUtils.navigateUpFromSameTask(this) function call the onBackPressed() activity method. I've tested it and it works.
b) Keep use NavUtils.navigateUpFromSameTask(this)
But implement the onSaveInstanceState and restore listView position during onCreate method of the ListFragment used by the A activity. (I've not tested this approach yet)
Which of this solutions is better? Or is there any other (much more better) solution?
Solution a) is pretty simple and straight forward, but b) is probably better because the default implementation of the up caret is used.
Any ideas are welcome. Thanks.
Solution c is the correct option. First, though, an explanation of the problem with solution a.
There is absolutely no point in having two back buttons in your Activity. Furthermore, option a actually breaks the up button. The point of the up button is to provide a way for users to stay within your app when they have landed in your app from an outside source. For example, if you land on activity B from an outside activity C and if you are using your option a, then pressing "up" in activity B will result in activity C being shown. The behavior you would want would be for activity A to be shown.
As you can see, solution b is on the right track. You definitely want to go up to A and not back to C. However, simply storing the state in onSaveInstanceState will not cause the state to be retained. This is because onSaveInstanceState only gets called if your application may be killed by the system. It is not guaranteed to be called if your application was destroyed manually, and it certainly won't be called when a new instance of your Activity is created. If the Intent starts a new activity, then it will not have its state restored from the other activity.
There solution, then, is that you must write anything persistent to a shared preference file (or a custom persistent alternative). When doing this you can guarantee that all instances of an Activity share the same state across multiple tasks so long as their onResume (or wherever you restore state) is called. OR:
If you know exactly how you want your navigation to work, you can avoid writing everything to persistent state by using a combination of Intent flags and Activity task affinities. If you want to use the same activity as up even if you navigate into the application from an outside source, then you can leave your Activity A's affinity as default (linked to the application) and use something like Intent.FLAG_ACTIVITY_CLEAR_TOP.
Personally, I'd try the Intent flag approach first and failing that fall back to writing the state persistently. You just don't really want scroll location sitting on persistent storage if you can avoid it..
check out this presentation: https://speakerdeck.com/jgilfelt/this-way-up-implementing-effective-navigation-on-android. It answers to all of your problems.
In my app I have situations where I need to get a user back to some activity that preceded(not necessarilly directly) the current one. All of those previous acitivities might need Intent parameters in onCreate.
So, my question is there any easy way to get user back to an activity that might not be the direct previous activity he's been on and is it possible to avoid manual workaround of saving/restoring those previous activities' intent parameters ?
Consider an example: there's a global search-bar that can provide users with suggestions on products; once they hit one of suggested items they get moved on a product-view activity where they can reload this activity with another product - walk through. After a couple of such reloads they might decide to go back to the activity where the search was initiated, but it might not the closest to the current one.
UPD: There also should be a possibility to go back in B activities sequence.
Using startActivityForResult() while loading a new activity and using finish() to close the launched activity on back press can solve your problem.
I have a problem cause when I go to different activities using startActivity function,
they always get created from scratch. Even if activity A was visited before, when I go to activity B and then A again, activity A is created again.
The problem is with back button, cause if I go to Activity A then B then A and then B,
in order to close the application I have to press back button 4 times.
I guess that it shouldn't act like it and user should be able to go to activity A when first pressed back button and the second press should close the application.
How to solve this issue?
Greetings
If you have activity transitions like:
Activity A -> Activity B
Activity B -> Activity A
and you want the user to go back to the same instance of Activity A in this case, maybe you just need to call finish() in Activity B after you call startActivity() for Activity A?
If this isn't helpful, please give us more information about what you are trying to do.
make sure you implement onSaveInstanceState and be prepared to restore your activity from a Bundle in onCreate. that's how you re-establish where you were when you return to an activity.
add launcheMode="singleTask" to your activity in the manifest
You need to set FLAG_ACTIVITY_SINGLE_TOP to your intent for launching activity A. Doing so will cause your previously created activity to re-use. Make sure you do handle your afterwards intents in onNewIntent method. For more info.
You need to set the flag FLAG_ACTIVITY_REORDER_TO_FRONT when you start activity A from B or vice versa, like
i = new Intent("....ActivityAorB");
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(i);
I've tried solutions proposed so far, however they didn't do it for me.
What did however, is using flag FLAG_ACTIVITY_CLEAR_TOP while starting activities.
Thanks for pointing me in the right direction though.
In my process I'm attempting to launch appB from appA using startActivityForResult and pass some data back and forth.
I'm probably not using it correctly because when appB launches (which it does correctly) its savedInstanceState (the onCreate param) is null.
Is that not the Bundle that the intent that I create in appA (prior to calling the appB) populates? If not where do I get that bundle?
Also, when I finish() appB which bundle do I pack with the data I want to hand back to appA in its onActivityResult handler?
Use Activity.getIntent().
Dr. D. There are actually at least four sets of state in your app. 1) The non view state of activity one (parent) which can be lost on a soft kill (phone rotation). 2) The non view state of activity two (child) which can be lost on a soft kill (phone rotation). 3) The state of data being passed from Activity 1 to 2 and back from activity 2 to 1. 4) The non view and view state of Activity 1 on a hard kill (user hit back button while Activity 1 has the focus.
I have sample code on 3) here, demonstrating pushing data using intent put extra and retrieving data using setResult and on 1), 2) here saving state using onSaveInstanceState.
Finally, I have some code here demonstrating how to encapsulate data using serializble objects and methods such as putSerializable and getSerializable.
I hope that helps,
Dr. JAL