Data in arrays isn't persisted - android

In my Android activitity, I am using two different arrays. First, I am declaring them, and then in the onCreate() method, I am instantiating them. However, when I populate them and then change the orientation, they are getting instantiated again in the and the data is lost.
public class MainActivity extends Activity {
private JSONArray first;
private JSONArray second;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
interestedSections = new JSONArray();
productsBought = new JSONArray();
}
//...
}
I tried to add if (savedInstanceState != null) before initializing the arrays, so as to initialize them for the first time only, however when I change the orientation, they are being null. What can I do in order to persist the data in the arrays throughout the whole application lifecycle please?

Check out this answer as onCreate is called when the screen is rotated:
Activity restart on rotation Android
Edit: If you want a quick and dirty way to make it work, just have a static initialized boolean and set it to true onCreate. Don't set the arrays to new arrays if initialized is true.

See onSaveInstanceState(), this is where you are supposed to save your arrays to the bundle.
By the way, Android sometime can kill the process and restore the activities later; the static variables will not survive this.

I had to declare the arrays as static and in the onCreate() method, I initialize them only for the first time:
public class MainActivity extends Activity {
private static JSONArray first;
private static JSONArray second;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (savedInstanceState == null) {
first = new JSONArray();
second = new JSONArray();
}
}
//...
}

Related

Android Activity not Retaining the Variables after being called by another Activity

I am developing a Quizz App in which an activity shows question and options from SQLite and on selecting option, another activity is showing result for 2000 ms(it has a timer)and then it calls First Activity via an Intent.
So, Most of the interaction is between 2 activities. But each time my MainActivity is called, it re-initializes all the variables again and again.
I am opening my database connection in onCreate() and also keeping a counter (that can count how many questions have been asked yet) whose value is not retained after the intent from Second Activity. I am worried on how to solve this.
I am a bit confused about the life cycle that is followed. Whether the call to First Activity from Second one starting with onCreate() or it's also initializing the instance variables again.
This is onCreate() method I wrote:
public class MainActivity extends Activity {
protected static final int SCORE_INCREMENT = 5;
TextView question;
Button score, opt1, opt2, opt3;
MyDatabaseManager dbManager;
QuizManager quizManager;
private int quiz_counter =1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbManager = new MyDatabaseManager(getApplicationContext());
dbManager.open();
quizManager = new QuizManager(MainActivity.this, dbManager);
Toast.makeText(MainActivity.this, "Asking The First Question", 0).show();
askQuestion();
}
}
Is there any difference between the above written code and the one I am writing now... if the activity is called again via an Intent
public class MainActivity extends Activity {
protected static final int SCORE_INCREMENT = 5;
TextView question;
Button score, opt1, opt2, opt3;
MyDatabaseManager dbManager = new MyDatabaseManager(getApplicationContext());
QuizManager quizManager = new QuizManager(this, dbManager);
private int quiz_counter =1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(MainActivity.this, "Asking The First Question", 0).show();
askQuestion();
}
}
This might be a silly question. But it's a bit confusing for me. Suggestions are welcome.
If you have variables that you want to maintain between changing activities, then you should either
Store them in SharedPreferences
or
Pass them between the Activites in the Intents (see Starting another activity)

setRetainInstance(true) does not persist member variables of the Fragment

I am using a View-less Fragment to store some data during orientation change of my Activity. It looks roughly like this:
public class BoardActivity extends BaseActivity {
private DataHandler mDataHandler;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// initialize the data handler
mDataHandler = (DataHandler)mFragmentManager.findFragmentByTag("data");
if (mDataHandler == null) {
mDataHandler = new DataHandler();
mFragmentManager.beginTransaction().add(mDataHandler, "data").commit();
// initialize the data
mDataHandler.mThreads = ...;
} else {
// here, the data is taken and the ListView is filled again.
fillView();
}
}
public static class DataHandler extends Fragment {
private Topic[] mThreads;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
}
}
What happens is, that when the Activity is left (vor example with the home button) and for some reason is killed in the background, the app crashes upon restart of that Activity. The reason is that although the Fragment mDataHandler is found by the FragmentManager, its Member variable (mThreads) is null.
How come the Fragment itself can be retained but its variables are set to zero?
How come the Fragment itself can be retained but its variables are set to zero?
The fragment was not retained. Retained fragments are retained only for configuration changes. You did not go through a configuration change. Your process was terminated, because Android needed the RAM to support other apps.

Android : Passing a value between activities

In my Android application I have to use common string value for all activities. "commonValue" is the common string value that I want to use in all activities. Relevant code of the main activity like this :
public class TestActivity extends Activity {
public String commonValue;//THE COMMON STRING FOR ALL ACTIVITIES
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
commonValue = "DemoValue";
}
}
In my next activity I created an object of "TestActivity" class and tried to assign "testValue" string to another string named "str"
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.testlist);
TestActivity obj = new TestActivity();//OBJECT OF MAIN ACTIVITY
String str = obj.commonValue;
}
but the "str" value in second activity does not equal to the value assigned in my first activity. Why is that & How can I do this?
Thanks!
Put your value in string.xml
<string name="common_value">DemoValue</string>
and use in any activity like this..
String common_value = getApplicationContext().getString(R.string.common_value);
Start using SharedPreferences in your app.
In your first activity you would do
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putString("commonValue", "DemoValue");
editor.commit();
In your second activity
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
String str = settings.getString("commonValue", null);
Try this -
TestActivity.java
public class TestActivity extends Activity {
public static String commonValue;//THE COMMON STRING FOR ALL ACTIVITIES
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
commonValue = "DemoValue";
}
}
another activity
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.testlist);
String str = TestActivity.commonValue;
}
If the value is always the same you can create a public static final variable and access it via TestActivity.COMMON_VALUE.
If you want to pass around a value between to Activities you should use Intents and add an extra with the value you want to pass.
As Sana has suggested, use SharedPreferences.
Alternatively, use a global constant class. If you want to stick with what you have, then you could try:
String str = TestActivity.this.commonValue;
Your existing code is creating a new instance of the activity, so it's not going to have the value you had set.
To pass data between activities use Bundle. and methods,
intent.putExtra()
and If you want to set data to be global to your app, then create an application class, and save the data there.
We have an Application file for each app you can declare the variable there and as the Application file can get from any activity so using the public getter setter and can get/set that
there are vaious oter metjod you can sue as mention on developer.android http://developer.android.com/resources/faq/framework.html
Singleton class
A public static field/method
A HashMap of WeakReferences to Objects (almost same as my above solution )
Persistent Objects
take a look on them as well
The reason why commonValue doesn't equal what you set in TestActivity onCreate method is because that function hasn't been called yet.
The solution for this is already mentioned by others. Like putting the value in a bundle.

View was clear data when screen rotation in Android

I have a View that was created on runtime then I draw some canvas on that View(runtime) after that I rotated my screen.All data was gone(reset).So I put the some code in AndroidManifest.xml like this
android:configChanges="keyboardHidden|orientation"
in my <activity> then I put a #Override function
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setContentView(R.layout.main);
LinearLayout layout = (LinearLayout) findViewById(R.id.myPaint);
layout.addView(mView);
}
but everything couldn't solved my problem.I want to keep my data from View(runtime) on every single rotation.
That's my onCreate function.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mView = new MyView(this);
setContentView(mView);
mView.requestFocus();
setContentView(R.layout.main);
LinearLayout layout = (LinearLayout) findViewById(R.id.myPaint);
layout.addView(mView);
}
You need to save and load the data you want to retain. Even though you're handling the screen rotation yourself when you modified the Manifest the way you did, you're still reloading the view yourself. Reread the reference document on Handling Runtime Changes. You need to store your data and reload it accordingly. Otherwise it will be lost when the application restarts or when you reload your ContentView.
http://developer.android.com/guide/topics/resources/runtime-changes.html
You could approach this a few ways.
I assume MyView is your own class which extends View. If so there are two methods which you may care to know, onSaveInstanceState() and onRestoreInstanceState(). When saving you create a parcelable that will contain enough data for you to re-render your view if it were to be destroyed and recreated.
class MyView extends View {
private String mString;
onDraw(Canvas v) { ... }
Parcelable onSaveInstanceState() {
Bundle b = new Bundle();
bundle.putString("STRING", mString);
return b;
void onRestoreInstanceState(Parcelable c) {
Bundle b = (Bundle) c;
mString = bundle.getString("STRING", null);
}
}
Activity has similar state saving mechanics allowed in onCreate and onSaveInstanceState() (inside Activity, not View in this case) which will allow the activity to reset the state of it's view to the state it desires.
This should solve most of your worries. If you are wanting to use the onConfigurationChanged method, then you should reclarify your question as it is not clear what the current behavior is that you aren't expecting in each situation (only using onConfigurationChanged, or only using onCreate, or using both, etc).
I've just used my data-class as singleton (java-pattern).
And it works fine.
--> Application is a Stop-Timer for Racing, where i can stop time from different opponents on the track, so i need the data for longer time, also if the view is repainted.
regz
public class Drivers {
// this is my singleton data-class for timing
private static Drivers instance = null;
public static Drivers getInstance() {
if (instance == null) {
instance = new Drivers();
}
return instance;
}
// some Timer-Definitions.......
}
Then in MainActivity:
// now the class is static, and will alive during application is running
private Drivers drivers = Drivers.getInstance();
#Override
public void onClick(View v) {
if (v == runButton1) {
drivers.startTimer1();
// do some other crazy stuff ...
}
}
// here i put out the current timing every second
private myUpdateFunction(){
time01.setText(drivers.getTimer1());
// update other timers etc ...
}

Classes & Activities in Android

Another Java/Android newbie...
My Activity contains a delcaration for a variable of a class that I've defined...
public Teams theTeams = null;
Within the onCreate method of this Activity, I create an object of that class...
Teams theTeams = new Teams();
I've been able to make some changes to this object...
theTeams.setName("A", "Jets");
... which assigns "Jets" to a string in the class.
However, from within a private method of the Activity, attempts to refer to "theTeams" give me a null pointer error. I guess there's something about object visibility that I'm not understanding. Can someone clarify?
You declared first public Teams theTeams = null;
Then in the onCreate method, you have this
Teams theTeams = new Teams();
So you are initializing a new theTeams object of type Team inside the onCreate, which you can see only in the scope of onCreate.
So when you call a method on theTeams in your private method, the method is called in the object you have declared first outside the onCreate (which is still null)
So inside, your onCreate, you have to use:
theTeams = new Teams();
Something like the following should work (untested):
private Teams theTeams = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
theTeams = new Teams();
}
private void myMethod() {
theTeams.getName();
}

Categories

Resources