My app has around 25 items that users can change attributes on. They can show/hide them, set the text, change the color, etc. And they can save multiple sets of these settings.
I'm trying to come up with the best way to handle this. I could use sharedpreferences and store the value of each attribute for each of the ~25 items and prefix them with the name of the saved set of settings. Then regardless of if any changes were made, load the values for everything on start/selection of a new set and save all values on close/save of new set.
I'm not sure that's the best way though. Anyone have ideas on how to do this?
PreferenceActivity is very powerful for such cases.
You can serialize your java objects that implements Serializable interface. Then you can save this serialized string to an internal file. Afterwards you can get these objects by deserializing objects. By using this method your data will be private and nobody will see your data, this is not the case when you use sharedpreferences. This method is very flexible so that you can save all objects that implements Serializable interface. I am using this method to save my preferences.
Related
I have an android application that has uses few serializable classes
(I can store and load them in JSON format using Google Gson library and it works like a charm).
Now I want to provide way for user to edit those objects in fashion similar to PreferenceActivity - they contain few strings, ints and doubles and PreferenceScreen just seems ideal for editing them.
Is there a way to 'abuse' PreferenceActivity to provide UI for editing my objects without actually storing data in shared preferences?
For example - if there was some callback to override that is called just before saving data, I could extract data, assemble my object and somehow prevent Android from messing with preferences?
SharedPreferences is an interface, so you should be able to provide your own implementation that stores data however you like. But the PreferenceManager used by PreferenceFragment only has a setter that takes a file name, not a custom implementation of SharedPreferences.
I looked into the source and found a roundabout way to use your own implementation. PreferenceFragment uses its hosting Activity as the Context for constructing a PreferenceManager. PreferenceManager subsequently calls Context#getSharedPreferences(String, int) to get the SharedPreferences that it will use. Therefore, you can override getSharedPreferences in the activity hosting your PreferenceFragment and return your custom implementation. Implementing SharedPreferences could be rather complicated since you'll also have to implement SharedPreferences.Editor, but it's doable. And if there's any chance of your overridden getSharedPreferences being used anywhere else, you should document that it uses a different backing store.
In the Android O preview, there's a new interface called PreferenceDataStore and a new setter in PreferenceManager that takes an instance of that interface. PreferenceDataStore looks much simpler to implement than SharedPreferences. But as I write this, most retailers are still selling L and M devices, so who knows when we'll see O.
First I would think if I really want to present objects editing with preferences UI since it might confuse a user.
If you still decide to go this way you can achieve it with:
Serialise every object in separate shared preference file and use preference activity how it is designed
Write own PreferenceManager and use reflection to replace private field in PreferenceActivity
The first one is straight forward and rather simple to implement, might have some performance implications. The second one might get tricky and probably requires more code to write.
I would still advice to revise decision to "re-use" PreferenceActivity for such case.
I'm new in programming for Android so maybe my question will be very easy to solve but still. I'm trying to make an array of different data types :
I have to add there :
int number
String name
int number_2
int time
int total
And my question now is how to implement it in easiest way, and how to get data from it. In case that I have to get a different records for this variables and store it into list .
Also have a question about way how to keep all values which I handle inside of my array.
I have to keep it because in my program I have to go back to other activities go forward to another and again collect data and add it to my array.
What will be the best and easiest solution ?
Thanks in advance for help
You could create the Array as an Array of Objects. All other classes are derived from Object, so you'll be able to store all types of objects in your Array. However, you would have to check the type of an object you get from the Array, before you'd be able to safely interpret as an object of a specific class. Moreover, you would have to use Integer instead of int.
If all (or at least multiple) of your elements you are intending to store in the Array are belonging to one (physical) entity, you could create a custom Class that holds its own properties as class members, and fill your Array with a list of instances of this Class.
Moreover, if you plan to add elements to your Array, you should use a List instead, e.g. an ArrayList.
As for retaining your data, you would have to either store it in a database, or save it to a file. In either way, you will have to save it upon close of the Activity, and load it again once the Activity starts
To pass the data across activities you will need to pass them using objects you can store in an intent. Seems like the best way to handle that is to either create a PREFS file to store the data or to create an object that extends Parcelable like here:
https://stackoverflow.com/questions/18593619/android-parcelable-object-passing-to-another-activity
Parcelables are preferable assuming you need all the data in a single object, you do not want to "putExtra" a bunch of fields and you also want to be sure data can pass from one activity to another. Otherwise, a simple Util class that reads and writes to a PREFS file is the way to go:
android read/write user preferences
A database is always another option, but seems well outside the scope of your question.
I am building an app which allows the user to define multiple objects of a specific type, lets call them "Person"'s. The "Person" object is defined as such:
class Person {
public String name;
public int age;
}
These "Person" objects will be serialised and stored within the app, either in SharedPreferences or via a Cloud storage mechanism. This can be considered handled and working.
My problem is that I need an editor interface to allow the user to change the "name" and "age" of any particular "Person" instance in their collection. In order to make my UI feel as much like stock as possible, I would like my editor interface to resemble the "Preference" interface which Android implements. As such I need a way to make a "PreferenceActivity" load and save it's preferences from/to a POJO.
The reason I am looking to do this is so that I have a UI that feels like something the user is used to using. My other choice is to mimic the style and create all the handling code myself, which will take a lot of time.
I imagined the process would be to override the "load" and "save" functions of a "PreferenceActivity" to pull/push the values from a POJO provided "onCreate" via an "Intent" - and the return this POJO as an activity result to the caller.
Is this achievable?
What is the purpose of having it this way? I fail to see why this would be useful nor how it would be feasible with regards to the reference of the pojo containing the data. If it was possible then the saving object would most likely be a generic key-object map, where you would need to extract the data from, which is exactly how the Preferences already work.
If the point of this is just to have the information in a Person object why not just make a method that creates one based on the saved preferences.
----- Additions
If you add a static/singleton data handler(repository) in the App that will contain all the persons while the App is executing, and that it has some kind of identifier for each person. Then you can pass the ID in the intent to the PreferenceActivity which will in turn fetch the person object from the data handler and fill in the values of the PreferenceActivity based on it.
Add another Preference to the PreferenceActivity named "Save" or similar, which you resolve and bind in the activity. When clicked this will fetch the currently entered information (which will be saved in the SharedPreferences) and create a Person instance out of it. It should then pass this object to the data handler which will add it (or update it if the ID is already there) to the repository of Persons. At this time you should probably consider serializing the whole repository and save it, one easy way is just to JSON it all and put it into the SharedPreferences. Don't forget that you need to load this data the first time you access the data handler so that the previously saved persons are accessible.
I would also recommend you create Interfaces for the data handling action in case you want to add new or replace the implementation to for example database operations instead.
This way you can use the PreferenceActivity for add/editing Persons. Even though I would prefer create your own UI for it.
I have checkboxes in my custom listview, I'm using a boolean array to save the state of these checkboxes. I want to make the state of checkboxes persistent through out the lifetime of the app.I know that this can be achieved through sharedpreferences, but I don't exactly know how this can be done.
I know that this can be achieved through sharedpreferences, but I don't exactly know how this can be done.
There is no option to push serializable objects into sharedpreferences. Because of that, you'll be forced to convert the boolean array to one of the supported types. The only one I can see making sense would be to convert the state of the array into a string like :
"0|1|0|1|1"
Then push that into the shared preferences. To do this you could use the Arrays.toString(boolean []). You will, however, have to write a parse method for extracting the value back out from the SharedPreferences. That is probably the easiest option to accomplish this.
I have an application which has some static variables.
These variables are stored in an independent Class named DataContext.
These variables are initialized from raw files at the application start (a method named DataContext.initConstant() is called in the onCreate() of MyApplication which extends Application).
(EDIT : the initConstant method use an AsyncTask to load this data from files).
When my application comes to the background for a certain time or when my application used to much memory, these static variables become null.
How can it be prevented?
If not what should I do with my static variables?
I have other data which are stored in static variables to be used across different activities, but I clear them or pass them to null in the onLowMemory() of MyApplication.
What is the best way to keep some data accessible between activities if these data are too big to be serialized in an Intent, a database can't be used (for whatever reason), and can't be stored in files through serialization either?
You can't. Android needs to free up memory from time to time. Imagine if all applications had a ton of static data that is supposed to be resident forever - how would you fit that in memory? It's a mobile phone. It doesn't have virtual memory.
(and 3): Anything that is intended to be persistent needs to be stored, either via SharedPreferences, a Sqlite database, or a file.
Most likely the issue is that your application is being killed while it is in the background, and then recreated when you come back to it. Check out the Activity Lifecycle documentation on when this might occur for a single activity. You need to make sure that you move anything stored in memory to more permanent storage at the correct point in time to avoid losing that information if the app gets killed.
I'm not sure what exactly you are storing, but it sounds like using Shared Preferences might work well. This page on Data Storage explains a number of different ways of more permanently storing data, including Shared Preferences.
If you weren't using raw files, I'd advise initializing when the class is loaded.
For instance,
public static Map<?,?> myStaticMap = new HashMap<?,?>();
static { //fill myStaticMap }
You do have some bigger concerns to worry about if you are loading files that way. For instance, what about I/O errors, or latency issues? You will get warnings in gingerbread (if you enable them) for doing I/O in your main thread. Perhaps you should have an object to retrieve these values instead of a class with static fields. (perhaps with a static cache, although you should synchronize on it before checking/changing it)
I assume this is a data cache problem.
Storing data in static class is not guaranteed to work when user swap apps often. Android system will reclaim any background activity when memory is low. Static class is definitely among this category.
The proper way to do it is to use sharedPreference to persist cache data.
You can create your own getter and setter of the data you want and wrap it around sharedPreference object. When you access using getter, you should always check if the value is empty or expired. You can store an update_time when using setter.
For activity specific data, you can just use getPreference(permission), if you want to share data across activities and other applications components, you can use getSharedPreference(name, permission).
Normally, the permission will be MODE_PRIVATE such that the data can only be accessed within your application.
You should group data and store in difference sharedPreference object. This is good practice because when you want to invalidate that group of data, it is just a matter of one liner.
editor.clear(); editor.commit()
If you want to cache complex object, you should serialize it. I prefer JSON format. So you need some conversion mechanism in place. To do this, I will create my data object class extending JSONable class. JSONable class will have toJSON() method and readFromJSON(). This is convenient when restore and serialize data.
I store a User object and a Client object in my static scope. I have noticed from time to time the reference becomes null. So now in my getters I check to see if this value is null and if so I restart the app.
Intent i = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(i);
I could have also chosen to reload the Client because I store the Access Token in prefs however I do so much initialization that I decided restarting the app would the best idea.
In your onResume() method you could query the static data to see if it is present and if not, load it back in again.
Instead of using the static variable u can use the shared preference for storing the value.
Note: for shared preference also you should not give heavy load.
I have solved this problem by having the super class with getter and setter function for storing and retrieving shared preference variable.
All class in my application extended the super class instead of activity.