- Java版數(shù)據(jù)保存
- Kotlin版本數(shù)據(jù)保存
- ContentProvider獲取Context
一、Java版數(shù)據(jù)保存
??在android開發(fā)中通常我們會使用SharedPreferences進行少量數(shù)據(jù)的保存,并對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();
??上面的代碼實現(xiàn)起來并不復雜,使用起來好像也不麻煩,但當我們需要增加保存的數(shù)據(jù)時,就需要在Setting對象中增加大量的set、get方法,而且使用的時候都要先獲去Setting實例。如果能像使用變量一樣使用SharedPreferences會多么美好?。?!
二、Kotlin版本數(shù)據(jù)保存
- kotlin屬性代理版本,可以讓我們像使用變量一樣存儲和獲取數(shù)據(jù)
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就可以解決這個問題。
- 創(chuàng)建自己的
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實現(xiàn) -->
<provider
android:name=".init.InitProvider"
android:authorities="${applicationId}.common.provider"
android:exported="false"
android:multiprocess="true" />
</application>
??這樣我們在主app:module中不用添加一句代碼就已經可以在需要Context的module中或得到Context對象。