Retaining variable value when stopping android activity - java

I've got two activities, A and B. Activity B can be opened by pressing a button in Activity A.
In activity B I have an integer variable which I would like to keep for when I return to activity B from A. My problem is when I press the back button to go from B to A the activity is destroyed.
I have overwritten the onBackPressed method to:
#Override
public void onBackPressed(){
Intent i = new Intent(this, Game.class);
startActivity(i);
}
I can see from my logs that activity B is in the state onStop() after back button is pressed, however, onRestart() is not being called so the activity must be getting killed for memory reasons.
I have read answers to other posts suggesting I use onSaveInstanceState() but when I try to access the bundle in onCreate() the bundle is null. Method onRestoreInstanceState() does not get called.
protected void onSaveInstanceState(Bundle savedInstanceState){
Log.i(LOG, "instance saving");
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt("score", userScore);
}
I have also tried SharedPreferences but this is not useful because I do not want my data to persist when the activity/application is intentionally destroyed.

I think your problem is in understanding the whole Task ecosystem. When you press back button you pop out your activity from the Task, because of that it is destroyed and onDestroyed() is called. To sum-up I think you are just getting every time a brand new activity. onSaveInstanceState() isn't called because activity is killed by user, not by the OS.
Take a deeper look at this developer tutorial.
Also I think those two must be helpful : me and me!

you can store variables in the app class https://developer.android.com/reference/android/app/Application.html or you can make your own singleton class for this
https://www.tutorialspoint.com/design_pattern/singleton_pattern.htm

Starting a Activity - A on onBackPressed will definitely kill the current Activity - B. Instead of starting Activity again just call onBackPressed in Activity - B and add a stage called onResume() which is called when you resume back to Activity B from A
Remove this:
#Override
public void onBackPressed(){
Intent i = new Intent(this, Game.class);
startActivity(i);
}
With this:
#Override
public void onBackPressed(){
super.onBackPressed();
}
When you coming back from A to B, in B #Override stage onResume() and in this you can save the value while coming back from Activity A.
Add this in Activity B:
#Override
protected void onResume() {
super.onResume();
// save values here for resume
}
Look the Activity Life Cycle:

Related

Managing the Android back stack and listeners with Firestore for optimizing document reads

I have activity A and activity B in Android.
In activity A there are a FirestoreRecyclerAdapter and a FirestoreRecyclerOptions object, which update in realtime a RecyclerView. I start activity B from a button in activity A, but I do not finish Activity A, so that when returning to Activity A I do not need to read again all documents already previously loaded within my recyclerView.
However, if I start a new intent from activity B to activity A, what happens to the Firestore listener in the old Activity A? Is it automatically terminated?
When you are using Query's addValueEventListener() method, you should remove the listener according to the life-cycle of your activity, as explained in my answer from the following post:
Should I actually remove the ValueEventListener?
If you are using the Firebase-UI library, once you start listening for changes in your onStart() method:
#Override
protected void onStart() {
super.onStart();
firestoreRecyclerAdapter.startListening();
}
You also need to stop listening for changes in onStop() method:
#Override
protected void onStop() {
super.onStop();
if(firestoreRecyclerAdapter != null) {
firestoreRecyclerAdapter.stopListening();
}
}

How to call function containing intent (in Activity A) from Activity B

I am Calling a function(present in fragment) from activity when back button is pressed
public void onBackPressed() {
new Home().show(Home.home_list,app.this);
}
Home is fragment of app activity
In show function I am calling an intent
public void show(final ArrayList<tile_data> data, final Activity activity) {
startActivity(new Intent(activity, Chat_topic_layout_for_user_group.class)
}
In doing so it gives me error : java.lang.IllegalStateException: Fragment Home{5deabab} not attached to Activity
My conclusion is that app is using show as function so it doesn't know about home.
So my question is how to call an "intent" present in some function in some activity or fragment from other activity??
Looks like startActivity is not being called in the right scope. Try specifying the scope and calling it like this: activity.startActivity(new Intent(activity, Chat_topic_layout_for_user_group.class)
Why don't you move the Show() function to the Activity? And for the titles create a getter function in the Home fragment, getTitles(). Now, when the event occurs trigger the Show() function directly in the activity passing (*HomeFragment*.getTitle() , *Activity*.this). Are your titles static? Because you are directly calling new Home(). If that's the case there won't be any issue in calling Show() function in the activity. You can explain your requirements in detail if this isn't up to par.
public void show(final ArrayList<tile_data> data, final Activity activity) {
activity.startActivity(new Intent(activity, Chat_topic_layout_for_user_group.class));
}

How to finish the main activity from other Activity

Hello how do you finish Main activity
Assume that there are 3 Activities and 1 Fragment
LoginActivity , MainActivity, infoFrgMent, ChangePwdActivity.
The scenario is when I loggedin in LoginActivitythen MainActivity will show up LoginActivity will finish() then i will go to my info which is 'infoFrgMent' then i want to change my password after i changed my password.
LoginActivity will shows up Again to relogin but whenever i try to press back MainActivity shows up and didn't finished.
You need to remove previous activities form stack
setFlags to intent from MainActivity to LoginActivity
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
refer : https://developer.android.com/guide/components/activities/tasks-and-back-stack.html
What you need is to add the Intent.FLAG_CLEAR_TOP. This flag makes sure that all activities above the targeted activity in the stack are finished and that one is shown.
Another thing that you need is the SINGLE_TOP flag. With this one you prevent Android from creating a new activity if there is one already created in the stack.
Just be wary that if the activity was already created, the intent with these flags will be delivered in the method called onNewIntent(intent) (you need to overload it to handle it) in the target activity.
Then in onNewIntent you have a method called restart or something that will call finish() and launch a new intent toward itself, or have a repopulate() method that will set the new data. I prefer the second approach, it is less expensive and you can always extract the onCreate logic into a separate method that you can call for populate.
To finish another Activity you have to create a static method to finish this Like here:
MainActivity.java
private static MainActivity activity;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
activity = this;
}
public static void finishThis()
{
try
{
if (activity != null)
{
activity.finish();
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
And call it like this:
AnotherActivity.java
MainActivity.finishThis();
That's it

Call a Method from another Method Android

I am not sure this workaround is the correct way to achieve my goal of having a prompt text in a spinner. What happens with this application is the spinner navigates to another Activity via an Intent and when the user navigates back to the Main Activity with the spinner they have two ways back. One with a Button and a click event the other by clicking the device BACK button. I am trying to call the code in the click event from the method that manages the device BACK button
I do not know how to call the click event from the device BACK button Method
#Override
public void onBackPressed() {
Toast.makeText(getApplicationContext(),"Use BACK BUTTON\n\n"+"On the Screen",Toast.LENGTH_LONG).show();
// I want to call goBack(View view) from here
// +++++++++++++++++++++++++++++++++++++++++++
}
public void goBack(View view){
Intent i = new Intent( PageTwo.this, MainActivity.class );
startActivity( i );
}
The reason I use this Intent to navigate BACK to the Main Activity is it reloads the variables in the Spinner
It looks like goBack(View) is most likely from an onClick setup in your layout XML. Since you aren't using the view, just pass null:
#Override public void onBackPressed() {
goBack(null);
}
I don't know if I get you right, if you just want to go back to the activity which started another activity, you can just call finish() method of Activity class:
#Override
public void onBackPressed() {
finish();
}
finish() reference

savedInstanceState always null

so i have this code in my OnsavedInstanceState
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
String [] a={"haha"};
savedInstanceState.putStringArray("MyStringarray", a);
Toast.makeText(context, "Saved array", Toast.LENGTH_SHORT).show();
}
and i have this code in my onCreate
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState==null){
Toast.makeText(this, "not there", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "is there", Toast.LENGTH_SHORT).show();
}
}
how come the toast always says not there? i opened the app then switched to another app and it showed the toast saved array but when i reopen the app it says not there even though the bundle should have the string array containing "haha".
Many thanks!
In onSaveInstanceState() you're modifying savedInstanceState and not saving this modified object. If super does a copy of your Bundle, then it will not save this modification.
Try calling super.onSaveInstanceState(savedInstanceState); at the end of the method instead.
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
String [] a={"haha"};
savedInstanceState.putStringArray("MyStringarray", a);
super.onSaveInstanceState(savedInstanceState);
Toast.makeText(context, "Saved array", Toast.LENGTH_SHORT).show();
}
The problem might be in how you have your activities defined in your manifest. For instance if your activity has the setting android:clearTaskOnLaunch="true" I don't think you will receive the saved bundle. See http://developer.android.com/guide/topics/manifest/activity-element.html for details on the various activity settings.
You might also check the other overridden methods. For example in you override one and do something odd you could mess the activity stack up. Do you call finish() anywhere in you code, if so remove it and see what happens.
Do not confuse this method with activity lifecycle callbacks such as onPause(), which is always called when an activity is being placed in the background or on its way to destruction, or onStop() which is called before destruction. One example of when onPause() and onStop() is called and not this method is when a user navigates back from activity B to activity A: there is no need to call onSaveInstanceState(Bundle) on B because that particular instance will never be restored, so the system avoids calling it. An example when onPause() is called and not onSaveInstanceState(Bundle) is when activity B is launched in front of activity A: the system may avoid calling onSaveInstanceState(Bundle) on activity A if it isn't killed during the lifetime of B since the state of the user interface of A will stay intact.

Categories

Resources