SharedPreferences牛刀小试

SharedPreferences是由Android提供的轻量级的存储方式,为什么叫它轻量级,主要是由于它只能够存储Java基本类型的数据。其底层实现也是借助共享文件(具体实现为XML文件),只不过Android基于Java的文件系统又再次做了一些封装,使其调用起来更为简单和方便。

本文还是通过写Demo的形式,来对SharedPreferences的常见使用方式来进行一个介绍。

SharedPreferencesActivity的代码如下:

package com.itachi.android.sharedpreferencesdemo;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.itachi.android.sharedpreferencesdemo.util.SharedPreferencesUtils;

public class SharedPreferencesActivity extends AppCompatActivity implements View.OnClickListener {
    private static final String TAG = "SharedPreferencesActivtiy";
    private static final String CUSTOM_PREFERENCES_NAME = "CustomPreferences";

    private EditText mUsername;
    private EditText mAge;
    private Button mWriteToApplications;
    private Button mWriteToActivitys;
    private Button mWriteToCustom;
    private Button mToOtherActivity;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_shared_preferences);
        mUsername = findViewById(R.id.user_name);
        mAge = findViewById(R.id.user_age);
        mWriteToApplications = findViewById(R.id.button_write_to_applications_preferences);
        mWriteToActivitys = findViewById(R.id.button_write_to_current_activitys_preferences);
        mWriteToCustom = findViewById(R.id.button_write_to_custom_preferences);
        mToOtherActivity = findViewById(R.id.to_other_activity);
        mWriteToApplications.setOnClickListener(this);
        mWriteToActivitys.setOnClickListener(this);
        mWriteToCustom.setOnClickListener(this);
        mToOtherActivity.setOnClickListener(this);
    }

    private void writeToPreferences(SharedPreferences preferences) {
        SharedPreferences.Editor editor = preferences.edit();
        String username = mUsername.getText().toString();
        int age = Integer.valueOf(TextUtils.isEmpty(mAge.getText()) ? "-1" : mAge.getText().toString());
        editor.putString("Username", username);
        editor.putInt("Age", age);
        editor.commit();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button_write_to_applications_preferences:
                writeToPreferences(SharedPreferencesUtils.getCurrentApplicationSharedPreferences(this, MODE_PRIVATE));
                break;
            case R.id.button_write_to_current_activitys_preferences:
                writeToPreferences(SharedPreferencesUtils.getCurrentActivityPreferences(this, MODE_PRIVATE));
                break;
            case R.id.button_write_to_custom_preferences:
                writeToPreferences(SharedPreferencesUtils.getPreferencesByName(this, CUSTOM_PREFERENCES_NAME, MODE_PRIVATE));
                break;
            case R.id.to_other_activity:
                Intent intent = new Intent(this, OtherActivity.class);
                startActivity(intent);
                break;
            default:
                break;
        }
    }
}

SharedPreferencesUtils的代码如下:

package com.itachi.android.sharedpreferencesdemo.util;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;

public class SharedPreferencesUtils {
    private static final String APPLICATION_NAME = "SharedPreferencesDemo";

    public static SharedPreferences getCurrentApplicationSharedPreferences(Context context, int mode) {
        return context.getSharedPreferences(APPLICATION_NAME, mode);
    }

    public static SharedPreferences getCurrentActivityPreferences(Activity activity, int mode) {
        // 调用的是Activity类的getPreferences方法
        return activity.getPreferences(mode);
    }

    public static SharedPreferences getPreferencesByName(Context context, String name, int mode) {
        // 调用的是Context类的getPreferences方法
        return context.getSharedPreferences(name, mode);
    }
}

先来分析一下SharedPreferencesUtils这个工具类的方法,其中分别调用了Activity类的getPreferences方法和Context类的getSharedPreferences方法来返回我们所需要的SharedPreferences对象。

我们先看一下ContextImpl中实现的getSharedPreferences(String name, int mode)方法(Context只是个抽象类,真正实现是在ContextImpl类中),如下:

    @Override
    public SharedPreferences getSharedPreferences(String name, int mode) {
        // At least one application in the world actually passes in a null
        // name.  This happened to work because when we generated the file name
        // we would stringify it to "null.xml".  Nice.
        if (mPackageInfo.getApplicationInfo().targetSdkVersion <
                Build.VERSION_CODES.KITKAT) {
            if (name == null) {
                name = "null";
            }
        }

        File file;
        synchronized (ContextImpl.class) {
            if (mSharedPrefsPaths == null) {
                mSharedPrefsPaths = new ArrayMap<>();
            }
            file = mSharedPrefsPaths.get(name);
            if (file == null) {
                file = getSharedPreferencesPath(name);
                mSharedPrefsPaths.put(name, file);
            }
        }
        return getSharedPreferences(file, mode);
    }

    @Override
    public SharedPreferences getSharedPreferences(File file, int mode) {
        SharedPreferencesImpl sp;
        synchronized (ContextImpl.class) {
            final ArrayMap<File, SharedPreferencesImpl> cache = getSharedPreferencesCacheLocked();
            sp = cache.get(file);
            if (sp == null) {
                checkMode(mode);
                if (getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.O) {
                    if (isCredentialProtectedStorage()
                            && !getSystemService(UserManager.class)
                                    .isUserUnlockingOrUnlocked(UserHandle.myUserId())) {
                        throw new IllegalStateException("SharedPreferences in credential encrypted "
                                + "storage are not available until after user is unlocked");
                    }
                }
                sp = new SharedPreferencesImpl(file, mode);
                cache.put(file, sp);
                return sp;
            }
        }
        if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||
            getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
            // If somebody else (some other process) changed the prefs
            // file behind our back, we reload it.  This has been the
            // historical (if undocumented) behavior.
            sp.startReloadIfChangedUnexpectedly();
        }
        return sp;
    }

具体细节就不仔细展开了,可以看到getSharedPreferences(String name, int mode)方法以我们传递进去的文件名创建了需要的xml文件,并调用getSharedPreferences(File file, int mode)方法返回我们需要的SharedPreferences对象。

我们再来看一下Activity类的getPreferences(int mode)方法,如下:

    /**
     * Retrieve a {@link SharedPreferences} object for accessing preferences
     * that are private to this activity.  This simply calls the underlying
     * {@link #getSharedPreferences(String, int)} method by passing in this activity's
     * class name as the preferences name.
     *
     * @param mode Operating mode.  Use {@link #MODE_PRIVATE} for the default
     *             operation.
     *
     * @return Returns the single SharedPreferences instance that can be used
     *         to retrieve and modify the preference values.
     */
    public SharedPreferences getPreferences(@Context.PreferencesMode int mode) {
        return getSharedPreferences(getLocalClassName(), mode);
    }

可以看到最终也是通过调用Context类的getSharedPreferences(String name, int modef)方法(Activity类实现了Context类)来返回SharedPreferences对象,只不过它默认传递了当前的Activity名称作为底层文件名。并且从这个方法的注释上我们也能看出,getPreferences方法返回了一个当前Activity私有的SharedPreferences对象,它的实现方式就是通过将当前Activity名称作为Preferences的名称。

再来看一下Demo中写了什么吧,我们在SharedPreferencesActivity中分别定义了三个按钮,将Username和Age写入到当前Activity私有的Preferences和两个共享的Preferences中。并且在OtherActivity中通过直接将SharedPreferencesActivity作为文件名获取SharedPreferences,来访问到SharedPreferencesActivity私有的Preferences,验证了前面分析的Context和Activity类的代码。

Demo的演示效果如下:

 通过Android Studio的Device File Explorer我们也可以看到,SharedPreferences默认被创建在"data/data/<应用包名>/shared_prefs/"目录下,如下图:

文件内容如下:

 对于SharedPreferences,它的使用是非常简单的,总结来说有以下几个特点,

1.轻量级,基于XML文件存储,只支持Java基本数据类型。

2.不支持多进程,其实关于这个,我觉得并不严谨,只能说它的使用初衷本就不是为了解决跨进程通信,只是为了解决一些简单的数据共享问题。且也可以另辟蹊径来在不同进程中访问,通过Context.createPackageContext(String packageName, int flags)方法来创建其他进程的上下文对象,进而访问其他进程的SharedPreferences文件。

3.数据量过大会影响它的读写性能,这个没有具体研究,只是看到书中和其他博主有提过,后面如果有工作需求能够深入了解的话,会再来分析这个问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值