Kotlin版本SharedPreferences数据保存
2020-04-07 本文已影响0人
狼性代码人
- Java版数据保存
- Kotlin版本数据保存
- ContentProvider获取Context
一、Java版数据保存
在android开发中通常我们会使用SharedPreferences
进行少量数据的保存,并对SharedPreferences
进行简单封装,代码可能如下:
- 简单对
SharedPreferences
包装,简化调用,避免遗漏apply()
。
import android.content.Context;
import android.content.SharedPreferences;
public class SharedPrefUtil {
private SharedPreferences mSharedPrefs;
private SharedPreferences.Editor mEditor;
public SharedPrefUtil(Context ctx, String name) {
mSharedPrefs = ctx.getSharedPreferences(name, Context.MODE_PRIVATE);
mEditor = mSharedPrefs.edit();
}
public void putString(String name, String value) {
mEditor.putString(name, value).apply();
}
public String getString(String name, String defaultValue) {
return mSharedPrefs.getString(name, defaultValue);
}
public void putLong(String name, Long value) {
mEditor.putLong(name, value).apply();
}
public Long getLong(String name, Long defaultValue) {
return mSharedPrefs.getLong(name, defaultValue);
}
.......
}
- 假设我们需要存储 用户名 和 用户ID 就会有下面的代码:
import android.content.Context;
public class Setting {
private static volatile Setting INSTANCE = null;
private final SharedPrefUtil mUtil;
private Setting(Context ctx) {
mUtil = new SharedPrefUtil(ctx, "setting.json");
}
public static Setting getInstance(Context ctx) {
if (INSTANCE == null) {
synchronized (Setting.class) {
if (INSTANCE == null) INSTANCE = new Setting(ctx);
}
}
return INSTANCE;
}
private String name = null;
private Long uid = -1L;
public String getName() {
if (name == null)
name = mUtil.getString("name", "");
return name;
}
public void setName(String name) {
mUtil.putString("name", name == null ? "" : name);
this.name = name;
}
public Long getUid() {
if (uid == -1L)
uid = mUtil.getLong("uid", -1L);
return uid;
}
public void setUid(Long uid) {
mUtil.putLong("uid", uid);
this.uid = uid;
}
}
- 调用的代码是这样的
final Context context = this.getBaseContext();
Setting.getInstance(context).setName("小三");
String name = Setting.getInstance(context).getName();
上面的代码实现起来并不复杂,使用起来好像也不麻烦,但当我们需要增加保存的数据时,就需要在Setting
对象中增加大量的set
、get
方法,而且使用的时候都要先获去Setting
实例。如果能像使用变量一样使用SharedPreferences
会多么美好!!!
二、Kotlin版本数据保存
- kotlin属性代理版本,可以让我们像使用变量一样存储和获取数据
class SharedPref<T>(
private val context: Context,
private val name: String,
private val defValue: T,
private val pref: String = "default",
private val commit: Boolean = false
) : ReadWriteProperty<Any?, T> {
private val prefs by lazy {
context.getSharedPreferences(pref, Context.MODE_PRIVATE)
}
override fun getValue(thisRef: Any?, property: KProperty<*>): T =
findPreference(findProperName(property))
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) =
putPreference(findProperName(property), value)
private fun findProperName(property: KProperty<*>) = if (name.isEmpty()) property.name else name
private fun findPreference(key: String): T = when (defValue) {
is Int -> prefs.getInt(key, defValue)
is Long -> prefs.getLong(key, defValue)
is Float -> prefs.getFloat(key, defValue)
is Boolean -> prefs.getBoolean(key, defValue)
is String -> prefs.getString(key, defValue)
else -> throw IllegalArgumentException("Unsupported type.")
} as T
private fun putPreference(key: String, value: T) {
val edit = prefs.edit().apply {
when (value) {
is Int -> putInt(key, value)
is Long -> putLong(key, value)
is Float -> putFloat(key, value)
is Boolean -> putBoolean(key, value)
is String -> putString(key, value)
else -> throw IllegalArgumentException("Unsupported type.")
}
}
commit.yes { edit.commit() }.other { edit.apply() }
}
}
- 假设我们需要存储 用户名 和 用户ID 就会有下面的代码:
private lateinit var APPCTX: Context
object Setting {
var name by SharedPref(APPCTX, "", "")
var uid by SharedPref(APPCTX, "uid", -1L)
}
- 调用的代码是这样的
Setting.name = "小三"
Log.e(Setting.name)
三、ContentProvider获取Context
上面的Context
来源都是通过外部传递过来的,如果在module
中使用就会变得不方便。不过通过在AndroidManifest.xml
中注册ContentProvider
就可以解决这个问题。
- 创建自己的
ContentProvider
对象,在此对象中就有我们需要的Context
属性。
class InitProvider : ContentProvider() {
override fun onCreate(): Boolean {
// 这里可以获得 context 属性
return false
}
override fun insert(uri: Uri, values: ContentValues?): Uri? = null
override fun query(
uri: Uri,
projection: Array<out String>?,
selection: String?,
selectionArgs: Array<out String>?,
sortOrder: String?
): Cursor? = null
override fun update(
uri: Uri,
values: ContentValues?,
selection: String?,
selectionArgs: Array<out String>?
): Int = 0
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int = 0
override fun getType(uri: Uri): String? = null
}
- 在
AndroidManifest.xml
注册我们定义的ContentProvider
对象。
<application>
<!-- 去context实现 -->
<provider
android:name=".init.InitProvider"
android:authorities="${applicationId}.common.provider"
android:exported="false"
android:multiprocess="true" />
</application>
这样我们在主app:module
中不用添加一句代码就已经可以在需要Context
的module
中或得到Context
对象。