![android 对象存储](https://img-blog.csdnimg.cn/img_convert/65e257819eca70be36478c56a40c83d3.png)
android 对象存储
在Android上使用SQLite的一种替代方法是将Java对象存储在SharedPreferences中。 在这里,我们将研究两种不同的方法。
为什么不为所有存储需求选择SQLite? 原因可能多种多样:除了对象定向数据库和关系数据库之间的阻抗不匹配外,对于某些简单的用例,SQLite可能会过大(带来更多开销),或者可能完全不喜欢SQLite的使用和语法。
例如,我们将使用以下User类:
/** User object to be saved in db */
public class User{
private int id; // used for object storage
private String userName;
private boolean registered;
private double score;
/** Constructor */
public User(int id, String userName, boolean registered, double score){
this.id = id;
this.userName = userName;
this.registered = registered;
this.score = score;
}
// getters and setters here...
}
唯一标识符id很可能由我们的服务器分发,尽管一旦我们创建了User并将其单独存储在SharedPreferences中(取决于应用程序的设计),我们也可以在设备本身上对其进行计算。 在这里,我们仅将其用作对象存储密钥。
接下来,我们需要编写我们的首选项类:
/** stores the user object in SharedPreferences */
public class UserPrefs{
/** This application's preferences label */
private static final String PREFS_NAME = "com.our.package.UserPrefs";
/** This application's preferences */
private static SharedPreferences settings;
/** This application's settings editor*/
private static SharedPreferences.Editor editor;
/** Constructor takes an android.content.Context argument*/
public UserPrefs(Context ctx){
if(settings == null){
settings = ctx.getSharedPreferences(PREFS_NAME,
Context.MODE_PRIVATE );
}
/*
* Get a SharedPreferences editor instance.
* SharedPreferences ensures that updates are atomic
* and non-concurrent
*/
editor = settings.edit();
}
//...
}
方法1:带有字段键的展平对象
这里的想法是,尽管SharedPreferences仅存储基本类型,但对象构造最终是基本的“包”。 因此,我们可以将一个对象分解为一组原语,并使用唯一键分别存储每个原语。 但是,如果要从存储中重建对象,则确实需要跟踪哪个保存的字段属于哪个对象。
因此,在对UserPrefs类中的给定User对象编写CRUD方法之前,我们需要在每个User类成员上定义唯一键。 为了方便起见,我们可以编写一种方法来确保整个键的唯一性:
/** The prefix for flattened user keys */
public static final String KEY_PREFIX =
"com.our.package.KEY";
/** Method to return a unique key for any field belonging to a given object
* @param id of the object
* @param fieldKey of a particular field belonging to that object
* @return key String uniquely identifying the object's field
*/
private String getFieldKey(int id, String fieldKey) {
return KEY_PREFIX + id + "_" + fieldKey;
}
请注意, getFieldKey()如何为我们提供每个字段名称和每个用户的唯一标识符。
现在,我们可以继续编写CRUD方法:
/** generic field keys */
private static final String KEY_USERNAME = "com.our.package.KEY_USERNAME";
private static final String KEY_REGISTERED = "com.our.package.KEY_REGISTERED";
private static final String KEY_SCORE = "com.our.package.KEY_SCORE";
/** Store or Update */
public void setUser(User user){
if(user == null)
return; // don't bother
int id = user.getId();
editor.putString(
getFieldKey(id, KEY_USERNAME),
user.getUsername() );
editor.putBoolean(
getFieldKey(id, KEY_REGISTERED),
user.isRegistered() );
editor.putFloat(
getFieldKey(id, KEY_SCORE),
user.getScore() );
editor.commit();
}
/** Retrieve */
public User getUser(int id){
String name = settings.getString(
getFieldKey(id, KEY_USERNAME),
"" ); // default value
boolean registered = settings.getBoolean(
getFieldKey(id, KEY_REGISTERED),
false); // default value
double score = settings.getFloat(
getFieldKey(id, KEY_SCORE),
0); // default value
return new User(id, name, registered, score);
}
/** Delete */
public void deleteUser(User user){
if(user == null)
return; // don't bother
int id = user.getId();
editor.remove( getFieldKey(id, KEY_USERNAME) );
editor.remove( getFieldKey(id, KEY_REGISTERED) );
editor.remove( getFieldKey(id, KEY_SCORE) );
editor.commit();
}
现在,我们可以从应用程序中的任何位置创建,检索,更新和删除任何用户对象:
// get a SharedPreferences instance
UserPrefs prefs = new UserPrefs( this.getApplicationContext() );
// get id from server or local storage
// then find User with that id
User user = prefs.getUser(id);
// operations on User, e.g.
user.setRegistered(true);
user.setScore(new_score);
// save
prefs.setUser(user);
// ...or delete
prefs.deleteUser(user),
对于嵌入式对象,我们递归应用相同的逻辑,并从User CRUD方法中调用其getter / setter方法。 这种扁平化对象的方法是手机上一个简单的,无需SQL的替代存储。 当然,随着嵌入对象数量的增加,它也有其局限性。
方法2:Google Gson
Gson是一个Java库,它提供简单的toJson()和fromJson()方法来将Java对象转换为JSON格式,反之亦然。然后,我们只需将JSON格式作为整个String存储在SharedPreferences中。 这种方法涉及到向我们的项目中添加新的库,但是更加方便:
// convert User object user to JSON format
Gson gson = new Gson();
String user_json = gson.toJson(user);
// store in SharedPreferences
String id = "" + user.getId(); // get storage key
editor.putString(id, user_json);
editor.commit();
// time flies...
// do the reverse operation
user_json = settings.getString(id, "");
user = gson.fromJson(user_json, User.class);
现在可以在我们的UserPrefs类中重写以前的CRUD方法,而无需使用用户ID以外的其他键。 那应该很简单,留给读者作为练习。
结论
我们研究了使用SharedPreferences存储对象的几种方法。 处理对象的其他选项是许多用于Android的ORM ( ORMLite , greenDAO , Sugar ORM , ActiveAndroid等),或NOSQL移动数据库,例如Couchbase Lite (此时为Beta版本)。 Couchbase Lite基本上是一个JSON数据库,而当数据模型变得复杂并且我们发现自己编写了大量样板化SQLite操作时,各种ORM可以大大简化我们的代码。 与所有旨在降低底层复杂性的抽象一样,ORM的缺点是泄漏抽象定律:
在某种程度上,所有非平凡的抽象都是泄漏的。
ORM和NOSQL替代品将成为后续文章的主题。
翻译自: https://www.javacodegeeks.com/2013/12/storing-objects-in-android.html
android 对象存储