博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
在偏好文件中存储数据
阅读量:4582 次
发布时间:2019-06-09

本文共 4838 字,大约阅读时间需要 16 分钟。

SharedPreferences对象使用常规的XML文件来存储数据,这些文件存储在应用程序的数据目录内。该XML文件的结构很简单,因为它只允许存储键/值对,不过Android API还提供了非常方便的抽象,允许开发者以类型安全的方式读写数据。

创建SharedPreferences对象最简单的方式是使用PreferenceManager.getDefaultSharedPreferences()方法,它会返回应用程序默认的偏好对象。使用该方式来存储主要的偏好设置很方便,因为框架会自动管理好文件名。但是,如果应用程序有多个偏好文件,最好使用Context.getSharedPreference()方法,它允许开发者自由地命名文件。如果只是创建和Activity相关的偏好文件,可以使用Activity.getPreference()方法,它会在调用时得到Activity的名字。

PreferenceManager.getDefaultSharedPreferences()创建的偏好文件名是由包名以及后缀_preferences组成的,如com.liyuanjinglyj.code_preferences。虽然很少需要这个名字,但如果要实现文件备份代理该名字就很重要。

SharedPreferences支持的存储值的类型有int,float.long.boolean,String以及set<String>对象。键名必须是一个有效的字符串,常见的做法是使用点符号按组结构化多个键值。

例如,如果偏好文件包含用于网络配置以及用户界面设置相关的值,可以通过为每个键添加network或者ui前缀来把它们分组。通过该方式,开发者可以轻松的管理键/值对,避免命名冲突。下面的例子演示了如何通过使用前缀并在单独的Java接口文件中定义键来结构化偏好数据:

 

public interface Constants {    public static final String NETWORK_PREFIX = "network.";    public static final String UI_PREFIX = "ui.";    public static final String NETWORK_RETRY_COUNT= NETWORK_PREFIX + "retryCount";    public static final String NETWORK_CONNECTION_TIMEOUT= NETWORK_PREFIX + "connectionTimeout";    public static final String NETWORK_WIFI_ONLY= NETWORK_PREFIX + "wifiOnly";    public static final String UI_BACKGROUND_COLOR= UI_PREFIX + "backgroundColor";    public static final String UI_FOREGROUND_COLOR= UI_PREFIX + "foregroundColor";    public static final String UI_SORT_ORDER= UI_PREFIX + "sortOrder";    public static final int SORT_ORDER_NAME = 10;    public static final int SORT_ORDER_AGE = 20;    public static final int SORT_ORDER_CITY = 30;}

 

 

推荐使用上面的方法访问存储的偏好值,而不是把键名硬编码在代码中。这样做可以避免误拼写,从而减少由于拼写导致的bug。

下面的代码演示了使用之前定义的Constants类来访问偏好文件:

 

private void readUiPreferences() {    SharedPreferences preferences            = PreferenceManager.getDefaultSharedPreferences(this);    int defaultBackgroundColor = getResources().            getColor(R.color.default_background);    int backgroundColor = preferences.getInt(            Constants.UI_BACKGROUND_COLOR,defaultBackgroundColor);View view = findViewById(R.id.background_view);view.setBackgroundColor(backgroundColor);}

 

 

要修改存储在偏好文件中的值,首先需要获取Editor实例,它提供了相应的PUT方法,以及用于提交修改的方法。在Android2.3之前,通过使用commit()方法把修改同步提交到存储设备中。但在2.3版本中,Editor提供了用于异步执行写操作的apply()方法。因为要尽可能地避免在主线程执行阻塞的操纵,apply()方法比之前的commit()方法更好。这使得在主线程直接从UI操作更新SharedPreferences很安全。

 

public void doToggleWifiOnlyPreference(View view) {    SharedPreferences preferences = PreferenceManager.            getDefaultSharedPreferences(this);    boolean currentValue = preferences.            getBoolean(Constants.NETWORK_WIFI_ONLY, false);preferences.edit()            .putBoolean(Constants.NETWORK_WIFI_ONLY, !currentValue)            .apply();}

 

 

上面的代码显示了使用点击监听器来切换存储在Constants.NETWORK_WIFI_ONLY中的偏好值。如果使用之前的commit()方法,主线程可能会被阻塞,导致用户体验差。使用apply()方法就不需要担心上面的问题。

在同一个进程中,每个偏好文件都只有实例。所以即便从二个不同的组件使用相同的名字获取二个SharedPreference对象,它实际上还是共享同一个实例,所以对于一个对象的改变会立即影响到另一个对象。

为了能在偏好值被修改的时候收到通知,开发者需要注册一个监听器回调函数,每当调用apply()或者commit()方法时都会触发该监听器回调函数。最常见的例子是,在Activity中修改偏好值应该影响后台Service的行为,如下所示:

 

public class NetworkService extends IntentService        implements SharedPreferences.OnSharedPreferenceChangeListener {    public static final String TAG = "NetworkService";    private boolean mWifiOnly;    public NetworkService() {        super(TAG);}    @Overridepublic void onCreate() {        super.onCreate();SharedPreferences preferences = PreferenceManager                .getDefaultSharedPreferences(this);preferences.registerOnSharedPreferenceChangeListener(this);mWifiOnly = preferences.getBoolean(Constants.NETWORK_WIFI_ONLY,                false);}    @Overrideprotected void onHandleIntent(Intent intent) {        ConnectivityManager connectivityManager                = (ConnectivityManager)                getSystemService(CONNECTIVITY_SERVICE);NetworkInfo networkInfo                = connectivityManager.getActiveNetworkInfo();        int type = networkInfo.getType();        if (mWifiOnly && type != ConnectivityManager.TYPE_WIFI) {            Log.d(TAG, "只执行WIFI网络");            return;}        performNetworkOperation(intent);}    @Overridepublic void onSharedPreferenceChanged(SharedPreferences preferences,String key) {        if (Constants.NETWORK_WIFI_ONLY.equals(key)) {            mWifiOnly = preferences                    .getBoolean(Constants.NETWORK_WIFI_ONLY, false);            if(mWifiOnly) {                cancelNetworkOperationIfNecessary();}        }    }    @Overridepublic void onDestroy() {        super.onDestroy();SharedPreferences preferences = PreferenceManager                .getDefaultSharedPreferences(this);preferences.unregisterOnSharedPreferenceChangeListener(this);}    private void cancelNetworkOperationIfNecessary() {        // 取消网络操作。}    private void performNetworkOperation(Intent intent) {        // 连上网络操作}}

 

 

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

 

转载于:https://www.cnblogs.com/liyuanjinglyj/p/4656562.html

你可能感兴趣的文章
(中等) HDU 4725 The Shortest Path in Nya Graph,Dijkstra+加点。
查看>>
sort-归并排序
查看>>
django 快速实现完整登录系统(cookie)
查看>>
.NET中的out和ref关键字
查看>>
Python之ftp服务器
查看>>
KMP预处理
查看>>
oracle的wm_concat函数实现行转列
查看>>
C语 三子棋小游戏
查看>>
[BZOJ 1861] 书架
查看>>
送给毕业生的一个学习建议
查看>>
基于redis+lua实现高并发场景下的秒杀限流解决方案
查看>>
Oracle 块修改跟踪 (Block Change Tracking) 说明
查看>>
阿里云 Redis 服务遇到的问题
查看>>
Jwt Token 安全策略使用 ECDSA 椭圆曲线加密算法签名/验证
查看>>
Window2008通过web.config进行限制ip访问
查看>>
浅析门户网站体育赛事CDN加速解决方案
查看>>
启动/关闭xp_cmdshell
查看>>
[PY3]——内置数据结构(8)——解构与封装
查看>>
进程、单线程和多线程
查看>>
python入门(3)python的解释器
查看>>