在偏好文件中存储数据

简介: 在偏好文件中存储数据

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);
    }
    @Override
    public void onCreate() {
        super.onCreate();
        SharedPreferences preferences = PreferenceManager
                .getDefaultSharedPreferences(this);
        preferences.registerOnSharedPreferenceChangeListener(this);
        mWifiOnly = preferences.getBoolean(Constants.NETWORK_WIFI_ONLY,
                false);
    }
    @Override
    protected 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);
    }
    @Override
    public void onSharedPreferenceChanged(SharedPreferences preferences,
                                          String key) {
        if (Constants.NETWORK_WIFI_ONLY.equals(key)) {
            mWifiOnly = preferences
                    .getBoolean(Constants.NETWORK_WIFI_ONLY, false);
            if(mWifiOnly) {
                cancelNetworkOperationIfNecessary();
            }
        }
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        SharedPreferences preferences = PreferenceManager
                .getDefaultSharedPreferences(this);
        preferences.unregisterOnSharedPreferenceChangeListener(this);
    }
    private void cancelNetworkOperationIfNecessary() {
        // 取消网络操作。
    }
    private void performNetworkOperation(Intent intent) {
        // 连上网络操作
    }
}
相关文章
|
供应链 数据库 开发者
深入了解数据库锁:类型、应用和最佳实践
深入了解数据库锁:类型、应用和最佳实践
|
JSON 小程序 前端开发
微信小程序框架(五)-全面详解(学习总结---从入门到深化)
微信小程序框架(五)-全面详解(学习总结---从入门到深化)
471 0
|
9月前
|
JavaScript API
鸿蒙开发:了解正则表达式
从给出的文本中,按照既定的相关规则,匹配出符合的数据,其中的规则就是正则表达式,使用正则表达式,可以使得我们用简洁的代码就能实现一定复杂的逻辑,比如判断一个邮箱账号是否符合正常的邮箱账号,再比如判断一个手机号是否正常的手机号,等等,正因为有了正则,得以让文本处理起来更加的简单。
188 7
|
10月前
|
云安全 存储 安全
带你读《阿里云安全白皮书》(十五)——云上安全重要支柱(9)
阿里云提供全面的数据安全保护措施,包括数据操作审计、全链路加解密、细粒度访问控制、可信计算和数据本地化存储等,确保客户数据的安全与合规。《阿里云安全白皮书(2024版)》详细介绍了这些技术能力,可点击链接下载完整版内容。
|
7月前
|
云安全 安全 Cloud Native
阿里云 SASE 2.0 能力迭代|构建一体化办公数据安全解决方案
阿里云 SASE 2.0 能力迭代|构建一体化办公数据安全解决方案
|
10月前
|
机器学习/深度学习 数据处理 Python
SciPy 教程 之 SciPy 插值 3
本教程介绍了SciPy中的插值方法,包括什么是插值及其在数据处理和机器学习中的应用。通过 `scipy.interpolate` 模块,特别是 `Rbf()` 函数,展示了如何实现径向基函数插值,以平滑数据集中的离散点。示例代码演示了如何使用 `Rbf()` 函数进行插值计算。
125 0
|
11月前
|
存储 数据采集 监控
CDGA\如何建立实现数据治理的效率价值框架:实践案例解析
数据治理是一个持续优化的过程。组织应建立健全的监督与评估机制,定期对数据治理工作进行评估,发现问题及时整改。广东药科大学通过数据全景图和数据监控大屏,实现了对数据治理成果的动态、多维度呈现与监控,为科学管理决策提供了有力支撑。
|
11月前
|
安全 网络安全 项目管理
企业在项目管理方面一般有哪些比较难解决的问题?
企业在项目管理方面需要面对的挑战多种多样,涉及从预算、沟通到风险管理等多个方面。为了应对这些挑战,企业需要采取有效的策略和方法,加强项目管理能力,确保项目的顺利进行和成功完成。
|
自然语言处理 数据挖掘 数据安全/隐私保护
云上电商解决方案:重塑电商生态,驱动数字化转型
随着数据泄露和隐私保护问题的日益严重,云上电商解决方案将更加注重数据安全和隐私保护。通过加强数据加密、访问控制等措施,确保用户数据的安全性和隐私性。 结语 云上电商解决方案作为电商企业数字化转型的重要工具,正逐步改变着电商行业的生态格局。通过提供灵活、高效、智能的电商服务,
709 8
|
11月前
提取mp4中的音频Pkt,以adts的方式写为aac文件
使用FFmpeg库从MP4文件中提取音频流,并将其转换为带有ADTS头的AAC文件,提供了两种方法:位运算和位域操作。
187 1