I have an Activity that has many fields (class fields/members). I want to set these fields by calling other activities (with startActivityForResult) but the field values are not kept. It looks like each time I return from another activity to my original one, a new instance is created and the fields are re-initialised (the onCreate() method is called each time I return from another activity, also onDestroy() is called on the original one each time I load another activity with startActivityForResult; I am never calling finish()). I hope I explained my problem well.
Any suggestions welcome.
Thanks,
Silviu
Make sure all your fields have unique id's as Android uses these id's to retain the field values when it redraws the activity.
Have you set android:launchMode="singleInstance" in the Android Manifest for the Activity where you have the startActivityForResult code?
If so remove that launchMode as it as some known issues with startActivityForResult.
Related
I have an activity containing some fragments. One of those fragments calls another activity. In this new activity I need to have an instance of the first activity. GetParent() returns null so I don't know how I can acomplish this...
MainActivity --contains--> Fragment1 --startActivity()--> SecondaryActivity
Is there some way to get the calling activity on the SecondaryActivity?
I don't think there is a good way of doing so.
It's really a bad practise to handle activity references like that, since android wouldn't be able to gc them when needed (orientation changes, lack of memory).
The best way is to pass all the data you need with Intent extras (intent that you use to start activity), and, if you need SecondActivity to return something, use Fragment1.startActivityForResult() for starting activity, and when done, use SecondActivity.setResult() to return desired result, you will need to override onActivityResult() to get the result (there are plenty tutorials about this).
If you absolutely need to hold references to something, you can use your own instance of Application class (don't forget to declare it in the manifest) to hold data for you while application is running.
In an app I'm making I have an Object to a class called Preferences in my MainMenu activity. I want to use this object in several pages. In the object is a class which contains an array with numbers. When I use it in another activity (Film) it changes one of the numbers in the object. Then I go back to the main menu and into a new activity (CurrentPrefs) in which I display the array of numbers on the screen. When I displayed the numbers they didn't contain the changes made in the Film file. So I started testing around with the variables a bit.
When I start the MainMenu, which is the start activity, it sets the object. Then when I enter film and check the object it still has the same name (object.toString()). I also checked to make sure that the values where changed correctly which they were.
Next I went back to MainMenu and checked again. The object still had the same name and the value were also like I changed them in Film.
Finally I entered the CurrentPrefs activity and there it goes wrong. The object suddenly has a different name and it also no longer contains the changes I made to it.
Why has the object changed and, more importantly, how can I make sure it doesn't change and stays the same everywhere?
There are any number of reasons why your object's values changed. Perhaps the previous Activity got destroyed and recreated without you realizing it.
You should check out Android's SharedPreference class. It is a way to store, edit, and retrieve preferences and have access to them in any Activity:
http://developer.android.com/reference/android/content/SharedPreferences.html
If you well know activity's lifecycle you can also understand why it happens. Probably some of your operation are delegated to onResume() method which is called whenever activity comes back from onPause() or immediately after onCreate(), while other operations reside in onCreate() called only when activity starts or after onDestroy(). I advise you to control this and trying to move all setText() in onResume() so that every updated object's variable will be read again.
can I use activiy one time(register activity) and switch the main launcher after using to different activity?
another question if I may,
If I create parameter x in one of the activities in my application, can I use this parameter in other activities?...If yes, how I can do that?
thanks :)
You cannot dynamically change the launcher activity once it has to be only 1 activity that is defined in the manifest file.
I would recommend having something like a landing or splash activity which checks a shared preference variable, to decide which activity to launch, for example either a login activity or another activity.
You should not access a variable in an activty from another activity, you should store these in data holding classes. however if you want to do it, for a good reason, simply make it static.
You cannot adjust the manifest after running your application. What you can do is have your default launcher activity write to SharedPreferences once it has been run once. Inside of that activity check to see if that preference has been set and if it has just finish that activity and launch your new activity, the user will not see anything if you do this in the onCreate of the launcher activity.
As for passing params between activities you should use intent extras. For example to pass a string use putExtra(String key, String value), and to get that parameter inside of the new activity use getStringExtra("Key").
For global variables accessable from different activities you can also extend Application class and then access it via getApplicationContext().
1. One time activity launch
You can't change the main launcher. It's a static information. What you could do is following:
// in the beginning of onCreate
// first launch could be loaded from shared preferences
// see 2. for more
if (!firstLaunch) {
// start another activity
finish();
return;
}
2. Use data in another activity
One way is to persist the data and load it somewhere else. You will find all information you need in the Data Storage article.
If your data is primitive you could try to pass it by intent to another activity. See Using integer from one class in another Android.
If it is complex you could try to implement an own Application class and use helper methods to access global data. See Android: Accessing resources without an Activity or Context reference.
Be careful with that, please read the Avoiding Memory Leaks article then.
My launch activity starts up another activity whose launch is set to single instance. In this 2nd activity, I have a public method. I then start up a 3rd activity and that activity needs to access the public method in the 2nd activity. I don't want to use startActivity and pass it extras because I assume the onCreate will get called (or am I wrong?) and I need to avoid the 2nd activity from reinitializing itself.
When an activity is started using startActivity, is it possible to gain access to the underlying class instance itself and simply call the method?
I actually came up with a simple solution. As a matter of fact you can access the underlying class of an activity. First, you create a class that is used to hold a public static reference to activity 2. When activity 2 is created, in its onCreate method you store "this" in the static reference. Activity 2 implements an interface with the methods that you want available to any other activity or object. The static reference you hold would be of a data type of this interface. When another activity wants to call a method in this activity, it simply accesses the public static reference and calls the method. This is no hack but is intrinsic to how Java operates and is totally legitimate.
It is not a good idea.
As I can understand method from second activity is actually not connected to particular activity while you want to call it from another one. So carry the method out to other (non-activity) class (maybe static method) and use it from both activities.
It's not directly possible to gain access to activity object started using startActivity (without using some hacks). And frankly you shouldn't even trying to accomplish this.
One Activity component can cycle through several Activity java object while its alive. For example, when user rotates the screen, old object is discarded and new activity object is created. But this is still one Activity component.
From my experience, when you need to do things you described, there is something wrong with your architecture. You either should move part of activity's responsibilities to Service or to ContentProvider, or use Intents, etc. Its hard to recommend anything more specific without knowing more details.
No there is no way to pass a reference via startActivity() however you can use some sort of shared memory to keep reference to your Activity. This is probably a bad design. However passing an extra with your Intent will not cause onCreate, that is completely related to the lifecycle.
If you have several activities onPause() is there a way to finish a specific activity?
edit: so for example, imagine on start activity 1 is called. Then activity 1 uses an intent to go to activity 2. then an update is made to the database and calls activity 1_new again so that it displays the updated database. At that point i want to get rid of the old activity 1.
It depends on what you want to do. You'll need to look at the AndroidManifest.xml spec for activity calls stacks.
Specifically android:launchMode
<activity android:launchMode="singleTop">
Careful though, launchModes are very tricky and can get you into trouble since it also depends on how the activity is launched from the Intent itself.
singleTop will essentially keep only 1 instance of that activity in the stack.
From the Docs:
If an instance of the activity already
exists at the top of the target task,
the system routes the intent to that
instance through a call to its
onNewIntent() method, rather than
creating a new instance of the
activity.
What I ended up doing here was calling startActivityForResult in the first activity. That way I was able to redisplay updated information from the second activity.