What Is More Efficient? Static, Data Passing, Shared Preferences, Database...

What is more efficient? Static, data Passing, shared preferences, Database...?

My opinions:

Each one is best depends on the scenario. Let me explain.

Static Variable:

Static variable are common ways to give access to whole application context. If you want to maintain few datas which is not necessary to be maintained after the application exited, this is the best one.

Passing data through Intent:

This is not a kind of data storing. This is a kind of data sharing. I think this is the best way to pass data from activity to activity. But maintaining the keys for values in Constants is a good programming thing.

Shared Preferences:

Shared Preferences is nothing but a simple table which has two columns. (key, value).

advantages:

  1. Fast retrieval
  2. Easy to understand and program

cons:

  1. Maintaining Keys are difficult if we store a lot of values.
  2. User can clear this at any time.

Database:

When we have a lot of values to store with complex structure, we are left with only one great solution, ie. DB.

advantages

  1. We can maintain structure of data.
  2. Android has nice and simple APIs to handle sqlite operations.

cons

  1. Operation is little bit slow comparing to shared preferences.
  2. user can clear this at any time.

So we found the major problem is we can't maintain the persistence whatever storage we use. A simple and effective solution is to maintain data online and sync it with mobile db each time the application is started.

Android SharedPreferences or SQLite Storing

Shared Preferences:

All shared prefs are stored in /data/data/[package name]/shared_prefs/[app name].xml, so i think there's no limit based on aechitecture.

Shared Preferences is nothing but a simple table which has two columns. (key, value).

Shared Preference size 8192 characters according to this documentation:
http://developer.android.com/reference/java/util/prefs/Preferences.html#MAX_VALUE_LENGTH

advantages:

  • Fast retrieval
  • Easy to understand and program

disadvantages

  • Maintaining Keys are difficult if we store a lot of values.
  • User can clear this at any time.

Database:

When we have a lot of values to store with complex structure, we are left with only one great solution, ie. DB.

advantages

  • We can maintain structure of data.
  • Android has nice and simple APIs to handle sqlite operations.

disadvantages

Operation is little bit slow comparing to shared preferences.
user can clear this at any time.

Reference

Where should I keep game level data?

For data that does not change I suggest you use a TypedArray-Resource

XML file saved at res/values/arrays.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="words">
<item>"aris"</item>
<item>"arsi"/item>
<item>"ris"</item>
//... other items
</string-array>
//... other arrays
</resources>

Then in code:

val array: Array = resources.getStringArray(R.array.words)

This way you have a clean separation between code and data and can not accidentally change it.

How to use SharedPreferences in Android to store, fetch and edit values

To obtain shared preferences, use the following method
In your activity:

SharedPreferences prefs = this.getSharedPreferences(
"com.example.app", Context.MODE_PRIVATE);

To read preferences:

String dateTimeKey = "com.example.app.datetime";

// use a default value using new Date()
long l = prefs.getLong(dateTimeKey, new Date().getTime());

To edit and save preferences

Date dt = getSomeDate();
prefs.edit().putLong(dateTimeKey, dt.getTime()).apply();

The android sdk's sample directory contains an example of retrieving and storing shared preferences. Its located in the:

<android-sdk-home>/samples/android-<platformversion>/ApiDemos directory

Edit==>

I noticed, it is important to write difference between commit() and apply() here as well.

commit() return true if value saved successfully otherwise false. It save values to SharedPreferences synchronously.

apply() was added in 2.3 and doesn't return any value either on success or failure. It saves values to SharedPreferences immediately but starts an asynchronous commit.
More detail is here.

More efficient ways to store information in Android Database

You can store information in Android in 4 ways:

  1. Persisting in a custom Database
    • Relational data
    • Multiple instances of the same structure
    • Don't lose data after the app process is killed
    • Heavier operations
  2. Persisting in Android's Shared Preferences
    • Simple data like primitive types (boolean, string, int..) that only occurs once
    • Don't lose data after the app process is killed
    • Light operations
  3. Persisting in a file in the internal/external memory
    • Depending on your choice, can be like 1. or 2.
    • Harder to maintain than 1. or 2.
  4. Holding it in memory
    • Data lost when your app process is killed
    • Lightest of all options

Which one are you interested in?

I would recommend 1. or 2. for most cases, but i still need more info


SQLite Database (using a DAO pattern that i recommend)

DatabaseHelper.class

public class DatabaseHelper extends SQLiteOpenHelper {

private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "your_app_name.db";
private static final String TABLE_MODEL_CREATE=
"create table " + Model.TABLE_NAME
+ " ( "
+ Model.COLUMN_ID+ " integer primary key autoincrement, "
+ Model.COLUMN_SOME_INTEGER + " integer, "
+ Model.COLUMN_SOME_STRING + " text "
+ " );";

public DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

// will run if there is no DB with your DATABASE_NAME
@Override
public void onCreate(SQLiteDatabase database)
{
database.execSQL(TABLE_MODEL_CREATE);
}

// will run if there is already a DB with your DATABASE_NAME and a lower DATABASE_VERSION than this
@Override
public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion)
{
// execute all the updates you want
database.execSQL(UPGRADE_1);
database.execSQL(UPGRADE_2);
// ...
onCreate(database);
}
}

ModelDAO.class

public class ModelDAO {

private SQLiteDatabase database;
private DatabaseHelper dbHelper;

public ModelDAO(Context context)
{
dbHelper = new DatabaseHelper(context);
database = GarcomApplication.db;
}

public void open() throws SQLException
{
database = dbHelper.getWritableDatabase();
}

public void close()
{
dbHelper.close();
}

public Model createModel(Model model)
{
ContentValues values = modelToContentValues(model);

long insertId = database.insert(Model.TABLE_NAME, null, values);
return getModel(insertId);
}

public Model updateModel(Model model)
{
ContentValues values = modelToContentValues(model);

int rowsAffected = database.update(Model.TABLE_NAME, values, Model.COLUMN_ID + " = " + model.getId(), null);
if (rowsAffected > 0)
{
return getModel(model.getId());
}

return null;
}

public void deleteModel(Model model)
{
database.delete(Model.TABLE_NAME, Model.COLUMN_ID + " = " + model.getId(), null);
}

public Model getModel(long modelId)
{
Cursor cursor = database.query(Model.TABLE_NAME, Model.allColumns, Model.COLUMN_ID + " = " + modelId, null, null, null, null);
cursor.moveToFirst();
Model novoModel = cursorToModel(cursor);
cursor.close();
return novoModel;
}

public List<Model> getModelList()
{
List<Model> modelList = new ArrayList<Model>();
Cursor cursor = database.query(Model.TABLE_NAME, Model.allColumns, null, null, null, null, null);

cursor.moveToFirst();
while (!cursor.isAfterLast())
{
Model model = cursorToModel(cursor);
modelList.add(model);
cursor.moveToNext();
}
cursor.close();
return modelList;
}

private ContentValues modelToContentValues(Model model)
{
ContentValues values = new ContentValues();
values.put(Model.COLUMN_SOME_INTEGER, model.getSomeInteger());
values.put(Model.COLUMN_SOME_STRING, model.getSomeString());

return values;
}

private Model cursorToModel(Cursor cursor)
{
Model model = new Model(cursor.getLong(0), cursor.getInt(1), cursor.getString(2));
return model;
}
}

Model.class

// when you have time, read about implementing Serializable or Parcelable in your models
// it will help you to transfer this whole object throughout activities etc
public class Model {

public static final String TABLE_NAME = "model";

public static final String COLUMN_ID = "id";
public static final String COLUMN_SOME_INTEGER = "some_integer";
public static final String COLUMN_SOME_STRING = "some_string";
private final String[] allColumns =
{
Model.COLUMN_ID,
Model.COLUMN_SOME_INTEGER,
Model.COLUMN_SOME_STRING
};

private long id;
private Integer someInteger;
private String someString;

// constructors, getters and setters

}

Usage:

ModelDAO modelDAO = new ModelDAO(someContext);
modelDAO.open(); // opening DB connection

Model newModel = new Model();
Model persistedModel = modelDAO.createModel(newModel); // inserting a new model
Model updatedModel= modelDAO.updateModel(persistedModel); // updating a model
modelDAO.deleteModel(updatedModel); // deleting a model

modelDAO.close(); // closing DB connection (NEVER FORGET ABOUT THIS!)

Shared Preferences

// getting access to SharedPreferences
SharedPreferences prefs = this.getSharedPreferences("com.example.app", Context.MODE_PRIVATE);

// reading data
Integer yourInteger = prefs.getInteger("your_integer_name", defaultIntegerValue);

// persisting data
SharedPreferences.Editor editor = mySharedPreferences.edit();
editor.putInteger("your_integer_name", yourInteger);
editor.commit();

Difficult to store Shared preferences value to SQLIte in Android and having null value stored

Supposing that you already know how to store and get the userid from the shared preferences.

In your addTask activity, add:

private String userId;
@Override
protected void onCreate(Bundle savedInstanceState) {
...
userId = sharedPreference.getString("USER_ID",null);
...
}

in the addItem() add:

private void AddItem() {
...
todo.setUserId(userId);
...
}

in the DB add() use this:

public void add(ToDo todoTask) {
...
values.put(USERID, todoTask.getUserId());
...
}

OR:

Another approach is to get the value directly from the DB class if you are sure that you will never insert task for other users.

public void add(ToDo todoTask) {
SQLiteDatabase db = this.getWritableDatabase();
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(ctx);
String d = sp.toString();

ContentValues values = new ContentValues();
values.put(TITLE, todoTask.getTitle());
values.put(CONTENT, todoTask.getContent());
values.put(user_Id,todoTask.getUserID(d));

db.insert(mTODO, null, values);
db.close();
}

and in the constructor save the context for further use.

private Context ctx;

public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.ctx = context;
}

Performace-Create object in every class or use static class for custom sharedpreferences

The answer depends a little on what role you want UserSession to fill. Do you want UserSession to be a simple wrapper for SharedPreferences or do you want it to be a single source of truth for your session data?

If you want it to act simply as a wrapper then I would make it a static class which does not store the context. Just pass the context and shared preferences in to each method that needs it.

public String getUserName(Context ctx, String sharedPrefFileName) {...do your tedious shared preference editing here...}

If you want the UserSession to store the state of the current "session", then I would recommend making it a singleton. This singleton could store the shared preference filename. It could also store a reference to context but you have to be careful how you construct this singleton.

You want to be careful not to leak your context reference. I don't know the lifecycle of UserSession but you should be careful when handing your context to it.

There are several different ways that you can 'store' context in a singleton. Android documentation says that you can make a custom Application class which exposes itself via a static public reference or... (from android docs)

In most situations, static singletons can provide the same
functionality in a more modular way. If your singleton needs a global
context (for example to register broadcast receivers), include
Context.getApplicationContext() as a Context argument when invoking
your singleton's getInstance() method.

I'm assuming UserSession calls getSharedPreferences to get a reference to the SharedPreferences. This method will always return the same instance (per filename) so you don't need to worry about calling this a lot since it doesn't create new instances.


is it ok to make singleton my custom sharedpreferences class which has
around 100 getter and setter methods

You can always break out the methods into smaller more modularized classes but it won't change the performance of your application. The number of methods in the singleton shouldn't affect your performance.

Should I persist data with SqlLite?

It's going to depends on the amount and complexity of your data.

If you have much data or the data you actually have can grow you should use SQLite.

If you just have some configuration data like if you can notify the user or something like this or some string which is your case you should use SharePreference.

Check this answer https://stackoverflow.com/a/9529787/6727154



Related Topics



Leave a reply



Submit