Java/Android - Most efficient way to store many variables - java

I'm creating an app and I need to store hundreds of strings that can be called or used in if/else functions. I was thinking about using SQLite to try and hold a load of them but I'm not very experience with it and I'm not too sure how I can manually store strings in it. Is there a simpler way to store many different strings besides using a large array or a database?

You need to ask yourself how you're going to use these strings. Will you load them all once into memory when the app starts up or will you constantly be pulling bits and pieces throughout the application's life-cycle? If your answer is the latter than a viable option in Android would be to use SharedPreferences which uses a key/value pair format to store data on the device. If your answer is the former then a database (SQLite) would probably be better.
See Google's documentation for more information on SharedPreferences.

Related

Android - best storage method to store objects (database or json/internal storage)

I'm new to Android development. I want to do a small app that need to store quotes from famous people. I'm going to use an Object quote to store each quote. The object will be simple and only use Strings.
I want the user to be able to add quotes, but I want them to be stored so they can be saved the next time the user open the app.
I've seen a lot of questions about how to store data and they usually give you lists of available technology. I'm wondering what are the common practices among experienced developers, what are the common use for each technology.
I know it's possible to use a database. But since I only want to store a list of quotes object I'm wondering if that wouldn't be too much.
I could store it in a file in the internal storage. But then how do I store it? Should a store it in json format and every time the user start the app I simply use the json to recreate the list of quotes.
I'm not sure which way would more practical or even if using json would be effective.
Thank you for you help!
I won't recommend you to use Shared Preferences since those are intended for very short data, say 100 kb to 1 MB. In you case you can store quotes either in an sqlite database or in a file. (One that suits your need). You can test between how much time does it take to write your quote to a file and to a database, both are good choices. In both cases you should create a wrapper class and use it according to your needs, which will make the working convenient.

How do I store objects if I want to search them by multiple attributes later?

I want to code a simple project in java in order to keep track of my watched/owned tv shows, movies, books, etc.
Searching and retrieving the metadata from an API (themovieDB, Google Books) is already working.
How would I store some of this metadata together with user-input (like progress or rating)?
I'm planning on displaying the data in a table like form (example). Users should also be able to search the local data with multiple attributes. Is there any easy way to do this? I already thought about a database since it seemed that was the easiest solution.
Any suggestions?
Thanks in advance!
You can use lightweight database as H2, HSQLDB or SqlLite. These databases can be embedded in the Java app itself and does not require extra server.
If your data is less, you can also save it in XML or Json by using any XMLParser or JsonParser (e.g. Gson()).
Your DB table will have various attributes which are fetched from API as well as user inputs. You can write query on the top of these DBs to fetch and show the various results.
Either write everything to files, or store everything on a database. It depends on what you want though.
If you choose to write everything to files, you'll have to implement both the writing and the reading to suit your needs. You'll also have to deal with read/write bugs and performance issues yourself.
If you choose a database, you'll just have to implement the high level read and write methods, i.e., the methods that format the data and store it on the appropriate tables. The actual reading and writing is already implemented and optimized for performance.
Overall, databases are usually the smart choice. Although, be careful of which one you choose. Some types might be better for reading, while others are better for writting. You should carefully evaluate what's best, given your problem's domain.
There are many ways to accomplish this but as another user posted, a database is the clear choice.
However, if you're looking to make a program to learn with or something simple for personal use, you could also use a multi dimensional array of strings to hold the name of the program, as well as any other metadata fields and treat the array like a table in excel. This is not the best way to do it, but you can get away with it with very simple code. To search you would only need to loop through the array elements and check that the name of the program (i.e. movieArray[x][0] matches the search string. Once located you can perform actions or edit the other array indexes pertaining to that movie.
For a little more versatility, you would create a class to hold the movie information with fields to hold any metadata. The advantage here is that the metadata fields can be different types rather than having to conform to the array type, and their packaged together in the instance of the class. If you're getting the info from an API then you can update or create the classes from the API response. These objects can be stored in an ArrayList and searched with a loop that checks for a certain value i.e.
for (Movie M : movieArrayList){
if(m.getTitle().equals("Arrival")){
return m;
}
}
Alternatively of course for large scale, a database would be the best answer but it all depends what this is really for and what it's needs will be in the real world.

How many simple Key-Value Pairs is too many for storing data in Android?

I'm currently trying to save data in Key-Value Pairs using Shared Preferences in Android. Well I'm doing this the question seems to arise (Considering I'm saving a decent chunk of data.) How many different Key Value pairs is considered still OK to save in my App? I'm currently looking at saving 100 to 150 different values. (All still having unique key string names.) Is that too much data to be storing with Shared Preferences?
This may be a stupid question, but the only stupid question is the one left unasked, and I couldn't seem to find an answer. Only knowledge I came by is that you should only save Primitive values using Shared Preferences. (Which I'm already doing so...)
-Thank You
How many is too many is really a matter of opinion. However, it's worth being aware how SharedPreferences work in order to get a feel for whether usingSharedPreferences` is the way to go.
As far as I know, there is no hard limit on the size of SharedPreferences, but SharedPreferences are stored in an XML file and when you first access the SharedPreferences the whole file is read and stored in memory so this in itself has an impact on the heap space used by your app and could lead to out of memory errors (partly depending on the size of the data, the available memory and what memory usage the rest of your app requires). Therefore, using SharedPreferences for a large amount of data will often mean you're using more memory than necessary. If you're reading the data from SharedPreferences into another data structure, you'll then have this data in memory twice. Also, XML isn't very efficient in terms of the space used on the filesystem.
I'm not saying it's wrong to use SharedPreferences but there's often a tradeoff between using something that might be more memory efficient (e.g SQLite DB) and give you extra functionality (searching, transaction support, etc.), compared to the simplicity of using SharedPreferences.
It also partly depends what you're storing - e.g. whether you're storing boolean values or long strings makes a huge difference in terms of memory usage. What you're doing with the data might make a difference as to which is the right way to go too. Do you need it to be scalable (e.g. you're storing 100 to 150 values now, but could that increase?).
If I were you, I'd consider how big my data is (i.e. amount of memory used not just number of key value pairs)? Might I need to store more in future? Would the extra functionality of SQLite be useful?
My gut feel based on the limited information you've provided is that I'd probably use SQLite, but I'm basing that on assumptions that scalability might be important and you're storing strings of more than a few characters, and even then I'm sure some people will disagree because "How much is too much" is subjective in this case.

sharing savegames between a demo and a full version in Android

I am currently developing an Android Game and my goal is to create a free/demo version of the game, so that the users can try it out. But I also want that the savegames from the demo are automatically imported in the full version.
The savegames I store in the applications private storage and they are basically JSON strings mapping several Java Objects. The user can create as many "new games" as he wants and there is an "auto save" and a "manual save" file for each game he started. To keep track of all the files, I have a list containing the filenames and some additional information (like the players name etc).
So basically there are quite a lot of small files handling the savegames. This may not be the most elegant approach, but it works quite well.
So here is my question: Lets say the user has started a game in the demo version (so there will be 3 files saved in the private storage of the demo version). How can I now access these files from within the full version?
The two versions won't be much different. They are actually the same, despite the limitations of the demo version. But I would be using the same code base.
I know there has been quite some questions about this issue in this forum and elsewhere, but I was not able to find a suitable solution. All I could find involved either:
storing the files in a world readable storage (like the SD-card) or
using the SharedPreferences
But I neither want the user to be able to read the savegames (or even alter it – because this could mess up the game) – so no sd-card, nor can I use the SharedPreferences, because each single savegame has approx. 200 lines of code (many many java objects translated into JSON) and mapping all those values and objects into some kind of key-value structure used for the SharedPreferences seems quite impossible to me.
Is this all messed up, or does anyone have an idea?
Thank you for taking the time, looking forward to hear your ideas!
Christoph
So I see just 2 Solutions:
The first is a WorldReadable SharedPreferences. You said, that you store JsonStrings, so there is no need to map them any further down, if you can make Objects out of your json-strings (I like to use Gson for this kind of work), you can simply store these
Strings inside SharedPreferences.
The second Way is to bother with ContentProviders and implement a ContentResolver interface. This is the safest way I can imagine for your use-case, but you have to implement a lot for it
What you can't avoid
There are two things that you can't avoid:
If the user decides to root the phone, you can't prevent a user from accessing it, doesn't matter what you do to make it harder.
If you want a second app to access the same data (the saved games) in a non rooted device, there would always be a away for user access it from outside your apps.
What can you do to make it harder
You can encrypt (i.e. using device IMEI) the data before store it in a file or shared preferences (together with a hash to prevent changes)
You can store the data in a SQLite database (would require more knowledge to change it), and encrypt before store it (even harder).
You can use SQLCipher to store it in a ciphered database (encryption will be transparent).
Regards.
You can use a shared Content Provider (here the general documentation about ContentProviders http://developer.android.com/guide/topics/providers/content-providers.html)
you then have to declare it as exportable using the flag: android:exported="true" in the manifest
example:
<provider android:name="[yourpackage_here].SavegameProvider"
android:authorities="[yourpackage_here].SavegameProvider"
android:exported="true" />
you will be able to open it within your new app.

Key-Value Database with Java client

I basically want to store a hashtable on disk so I can query it later. My program is written in Java.
The hashtable maps from String to List.
There are a lot of key-value stores out there, but after doing a lot of research/reading, its not clear which one is the best for my purposes. Here are some things that are important to me.
Simple key-value store which allows you to retrieve a value with a single key.
Good Java client that is documented well.
Dataset is small and there is no need for advanced features. Again, I want it to be simple.
I have looked into Redis and MongoDB. Both look promising but not ideal for my purposes.
Any info would be appreciated.
If your dataset is small and you want it to be SIMPLE. why don't you serialize your hashmap to a file or rdbms and load it in your application?
How do you wan't to "query" your hashmap? key approximation? value 'likeness'? I don't know, seems overkill to me to mantain a keyvalue storage just for the sake of.
What you are looking for is a library that supports object prevalence. These libraries are designed to be simple and fast providing collection like API. Below are few such libraries that allow you to work with collections but behind the scenes use a disk storage.
space4j
Advagato
Prevayler
Before providing any sort of answers, I'd start by asking myself why do I need to store this hashtable on disk as according to your description the data set is small and so I assume it can fit into memory. If it is just to be able to reuse this structure after restarting your application, then you can probably use any sort of format to persist it.
Second, you don't provide any reasons for Redis or MongoDB not being ideal. Based on your (short) 3 requirements, I would have said Redis is probably your best bet:
good Java clients
not only able to store lists, but also supports operations on the list values (so data is not opaque)
The only reason I could suppose for eliminating Redis is that you are looking for strict ACID characteristics. If that's what you are looking for than you could probably take a look at BerkleyDB JE. It has been around for a while and the documentation is good.
Check out JDBM2 - http://code.google.com/p/jdbm2/
I worked on the JDBM 1 code base, and have been impressed with what I've seen in jdbm2
Chronicle Map should be a perfect fit, it's an embeddable key-value store written in pure Java, so it acts as the best possible "client" (though actually there are no "client" or "server", you just open your database and have full read/update in-process access to it).
Chronicle Map resides a single file. This file could be moved around filesystem, and even sent to another machine with different OS and/or architecture and still be an openable Chronicle Map database.
To create or open a data store (if the database file is non-existent, it is created, otherwise an existing store is accessed):
ChronicleMap<String, List<Point>> map = ChronicleMap
.of(String.class, (Class<List<Point>>) (Class) List.class)
.averageKey("range")
.averageValue(asList(of(0, 0), of(1, 1)))
.entries(10_000)
.createPersistedTo(myDatabaseFile);
Then you can work with created ChronicleMap object just as with a simple HashMap, not bothering with keys and values serialization.

Categories