Considering the following scenario. There's an Activity_1, which creates another Activity_2, in Activity_1, some data are produced which needs to be recorded, and Activity_2 starts another Activity_1.
a) Will Activity_1 be brought to the top of calling stack, or will there be another instance Activity_3 that's the same class with Activity_1?
b) How do I recover the data generated in Activity_1, and make the show in Acitivity_3(or Activity_1 if it's simply brought to top). i.e., maintain the historical data in Activity_1
Well the answer is what flags you are setting during the start of new activity or calling an old activity. Below link will answer your question.
Tasks and Back Stack and SharedPreference
Would suggest to read the whole article and you will never have any problems.
Related
How can I save activity state (B) when moving to previous activity (A) and how to restore it's previous state when moving back (to activity B)?
SCENARIO
Content of activity B can be changed by user. After finishing work, performed changes can be persisted (e. g. saved to local DB). Before persisting, user may want to navigate back to previous activity. At this point, "work session" should be somehow saved temporary in memory. After returning back to activity B "work session" should be restored, so user can continue in work.
APPROACHES
Standard methods onCreate(Bundle) and onSaveInstanceState(Bundle) are used to restore/save activity state when device configuration changes (e. g. on rotate). As onSaveInstanceState(Bundle) is not part of activity's life-cycle, this method does not get called on "back-press" when activity is destroyed (by default finish() is called). The same applies for onRestoreInstanceState(Bundle). Obviously these methods alone are not sufficient to restore activity state after lefting an activity.
Transfering bundle state between activities
One way I can think of is to override onBackPressed() in such way it will start an Intent to previous activity A with bundle state Intent#putExtras(Bundle) of current activity B. When moving back, starting an Intent to activity B, this bundle state will be delivered back Intent#putExtras(Bundle) to restore the state of activity B. However this also require to override onCreate(Bundle) and onSaveInstanceState(Bundle) in A so bundle state of B would not be lost on configuration change before navigating back to B.
Not finishing an activity on back-press + non-default launchMode
Another way (more cleaner) is to override onBackPressed() so that it would start Intent to previous activity A without calling finish() of current activity B so activity B will hang in memory in paused state (waiting for resume). To resume activity B, manifest configuration android:launchMode="singleInstance" is required so android will use existing activity (paused B) instead of creating new one (B2) when navigating back to activity B (startIntent(B.class)).
Details: launchMode singleInstance creates singleton activity in new task (task = set of activities with the same group id i. e. affinity, normally app activities have the same affinity i. e. app = single task).
Drawback: transition animations does not work with singleInstance mode. It seems that singleInstance task may not be fully initialized at animation time. For more details: Custom animation doesnt work on SingleInstance Activity.
Saving activity state to SharedPreferences
Saving activity state to SharedPreferences on "back-press", restoring activity state from preferences in onCreate(Bundle) like in following link Save activity state to SharedPreferences.
Drawback: unable to save Bundle state (only primitives: putInt, putString, ...).
Others
Some of the methods listed in Share data between activities can be used. Answers from this link refers to developer.android.com/guide/appendix/faq/framework.html which is unfortunately broken. Here is an alternative source http://wing-linux.sourceforge.net/guide/appendix/faq/framework.html.
About sharing data via Application object:
Don't Store Data in the Application Object,
Using the Android Application class to temporary persist data.
Based on Application class documentation, using static singletons over Application is more preferable.
Base class for maintaining global application state. ...
Note: There is normally no need to subclass Application. In most situations,
static singletons can provide the same functionality in a more modular
way. If your singleton needs a global context (for example to register
broadcast receivers), include Context.getApplicationContext() as a
Context argument when invoking your singleton's getInstance() method.
It seems that putting data in Application object or static singleton is so far the best solution for this problem.
QUESTION
Is there any build-in solution for this (without need of overriding onBackPressed())? For example saving activity on back-stack with it's state. If not, what is the common pattern to save activity state in such situation?
RELATED POSTS (just to link them with this post)
How do I save temporary data on android?
For an alternative way to handle this, you can map your view's states to a data structure and save it as an object notation (such as json) to your local and when your activity is created / re-created you can read your state from local and bind them with your views.
For more information and example, you can check Spotify's presentations and open source project which contains information about how they manage application's ui from apis. (I know it's not exactly what you're trying to do but you may find some tricks.)
If you need to save your data in your activities, you can use Local Db or in-memory cache.
When you back out of an activity, the activity is not just destroyed programmatically, but also conceptually. In other words, the user expects it to be gone. We talk about saving activity state in situations where the activity object is destroyed but the user perceives that it still exists, such as during configuration changes or when it's in the background or backstack.
What you're trying to save is properly thought of as application state, not activity state. As such, SharedPreferences is an appropriate place for it. Whether it's the best solution is a matter of opinion and depends on your use case.
I have activities like A->B->C->D. How can I close the A activity if I have 4 activities on my stack? Also later when I open activity E i want B to be closed aswell, so I want to have C->D->E only.
There is no such as a direct way to manage activities number in stack. So far I know that stack is big as much as available memory.
Also consider LaunchMode and whether activities are in the same task or not.
So, you might implement your own Activity manager to finish un-wanted activities.
Here is briefly how I see the solution:
Create a model to store activity, its index in stack, date ..i.e. ActivityItem
Create an empty List of ActivityItem in your custom Application. To avoid memory leak, use WeakReference. create a public setter adActivity to add and manage activities
Better approach to create activity base class and reuse it as superClass wherever you want to manage count of running activities. instead of repeating same implementation for each different activity.
OnCreate in your base Activity call adActivity and pass current activity.
adActivity job is firstly clean the list of destroyed activities. thanks WeakReference. Then manually kill older activities before last 3 items in your list. It's not easy as it looks.. for example: SingleInstance and rotation will make it challenge to achieve this :-)
that is it.
Good luck,'.
When you start activity use
startActivityForResult(intent,code);//different code for all activity
and call
finishActivity(code);//which activity do you want to close?
You can call:
finish();
after:
startActivity(intent);
In every activity that you want to close, when you open another activity.
I have got 2 activities - "A" contains fragment with a list of conversations, "B" represents a conversation (shows it's messages), in B I can also send a new message.
I would like to be able to update A's list of conversations every time a message is sent in B, so when I click android's back button, A activity's view is updated.
The core of the problem for me, is that I'm not starting A through an Intent when I click the android's back button, so I don't know how to get this effect.
Thank you for your help!
When A is on the backstack, there's no guarantee that an instance of A even exists in memory. The answer to the question of how to manipulate A from B is don't.
Some correct ways of doing it:
If your model (the list of conversations) is Parcelable or Serializable, you can pass it between activities via Intent. You can pass it back from B to A if you start B for result and retrieve it from the Intent returned to A's onActivityResult.
Make the model persistent, like in a database or SharedPreferences file.
Put the model in a bound Service. This would be faster than having each activity load it from persistent storage, but you may still need to make it persistent so you don't lose it when the Service shuts down.
I have 2 major activity in my project Connect+Details and Menu. After I switch between the first activity to the second everything goes well. the problem start in returning back from 'Menu' to 'Connect+Details'.
when I use the back key to switch between the second activity and go back to the first everything goes well.
problem start when I use this code:
Intent myIntent = new Intent(Menu.this, ConnectActivity.class);
startActivity(myIntent);
I do go back to 'Connect+Details' but every detail in that activity is lost.
my question is simple, how can i go back to previews activity and still have the details used in that activity.
Edit:
the same thing goes even when I am in the 4th, 5th activity so finish() didn't help me.
You probably want to either save your data in SharedPreferences or in a database then use the saved data to repopulate your Activity. You can use SharedPreferences to save a key/value pair when you leave your Connect Activity and this will persist even if your app is closed.
If there will be a lot of data stored then you may consider using an SQLite DB. This can be a little trickier to set up and use but may be worth it if you are storing a lot of data...especially if its for different users.
Both of these options will persist your data when you leave the Activity or the program. You could also use a static Array but one of the first two options will probably be better for you.
The Storage Options Docs has some decent examples to get you started, especially if you decide that Shared Preferences will work for you.
Edit
Unless something has changed, you can't store serializable objects in SharedPreferences. But Here is a SO link that discusses saving them to a file and reading from there. Maybe this will help you.
Don't use Intent to move from 'Menu' to 'Connect+Details' instead call finish(); from it
Only use intent in first class to move to second ie;'Connect+Details' to 'Menu'
Don't call finish() in Connect+Details
I'd like the activity stack for my app to contain multiple instances of the same activity, each working on different data. So I'd have activity A working with data a, b, c and d in my activity stack ad I'd have 4 instances of activity A that I'd call A(a), A(b), A(c) & A(d). I'd also like to arrange it so that if the user asks to work with data c again then it won't start a new activity, but rather will just bring the already running activity A(c) to the front.
Any suggestions on the best way to achieve this?
So I'd have activity A working with
data a, b, c and d in my activity
stack ad I'd have 4 instances of
activity A that I'd call A(a), A(b),
A(c) & A(d).
That will happen by default.
I'd also like to arrange it so that if
the user asks to work with data c
again then it won't start a new
activity, but rather will just bring
the already running activity A(c) to
the front.
I do not believe that is possible unless you create distinct activities for each letter.
I'm not sure you can do it the way you have it described because fiddling with the activity stack like that is not supported AFAIK.
What you could do instead is just use a tab based activity. Each tab could be another instance of activity A working on a different dataset.
I agree with Falmarri (comment), you cant "switch between activities" in the way you are describing. You can however store that data somewhere (file, database, service, global variable, ext.). Where you choose to store that data (a, b, c, d) is up to you and depends on what kinds of functionality you need your data to have.
As for how you "switch" from one to the other, that is somewhat easier than you might think. you dont actually have to "switch" from one activity to the other, you can just swap our all the data. its is perfectly legal (though not always recommended) to have your entire app exist in ONE activity, and merely switch layouts over and over.
My suggestion would be to swap out the data within one activity. you could even specify which data set you want to load initially in your intent filter.