Android - Save key-value data(基于 SharedPreferences)

Save key-value data

If you have a relatively small collection of key-values that you’d like to save, you should use the SharedPreferences APIs. A SharedPreferences object points to a file containing key-value pairs and provides simple methods to read and write them. Each SharedPreferences file is managed by the framework and can be private or shared.

This page shows you how to use the SharedPreferences APIs to store and retrieve simple values.

Note: The SharedPreferences APIs are for reading and writing key-value pairs, and you should not confuse them with the Preference APIs, which help you build a user interface for your app settings (although they also use SharedPreferences to save the user’s settings). For information about the Preference APIs, see the Settings developer guide.

Get a handle to shared preferences

You can create a new shared preference file or access an existing one by calling one of these methods:

  • getSharedPreferences() — Use this if you need multiple shared preference files identified by name, which you specify with the first parameter. You can call this from any Context in your app.
  • getPreferences() — Use this from an Activity if you need to use only one shared preference file for the activity. Because this retrieves a default shared preference file that belongs to the activity, you don’t need to supply a name.

For example, the following code accesses the shared preferences file that’s identified by the resource string R.string.preference_file_key and opens it using the private mode so the file is accessible by only your app:

Context context = getActivity();
SharedPreferences sharedPref = context.getSharedPreferences(
        getString(R.string.preference_file_key), Context.MODE_PRIVATE);

When naming your shared preference files, you should use a name that’s uniquely identifiable to your app. An easy way to do this is prefix the file name with your application ID. For example: "com.example.myapp.PREFERENCE_FILE_KEY"

Alternatively, if you need just one shared preference file for your activity, you can use the getPreferences() method:

SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);

Caution: The MODE_WORLD_READABLE and MODE_WORLD_WRITEABLE modes have been deprecated since API level 17. Starting with Android 7.0 (API level 24), Android throws a SecurityException if you use them. If your app needs to share private files with other apps, it may use a FileProvider with the FLAG_GRANT_READ_URI_PERMISSION. For more information, also see Sharing Files.

If you’re using the SharedPreferences API to save app settings, you should instead use getDefaultSharedPreferences() to get the default shared preference file for your entire app. For more information, see the Settings developer guide.

Write to shared preferences

To write to a shared preferences file, create a SharedPreferences.Editor by calling edit() on your SharedPreferences.

Note: You can edit shared preferences in a more secure way by calling the edit() method on an EncryptedSharedPreferences object instead of on a SharedPreferences object. To learn more, see the guide on how to work with data more securely.

Pass the keys and values you want to write with methods such as putInt() and putString(). Then call apply() or commit() to save the changes. For example:

SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putInt(getString(R.string.saved_high_score_key), newHighScore);
editor.apply();

apply() changes the in-memory SharedPreferences object immediately but writes the updates to disk asynchronously. Alternatively, you can use commit() to write the data to disk synchronously. But because commit() is synchronous, you should avoid calling it from your main thread because it could pause your UI rendering.

Read from shared preferences

To retrieve values from a shared preferences file, call methods such as getInt() and getString(), providing the key for the value you want, and optionally a default value to return if the key isn’t present. For example:

SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
int defaultValue = getResources().getInteger(R.integer.saved_high_score_default_key);
int highScore = sharedPref.getInt(getString(R.string.saved_high_score_key), defaultValue);

准备

IDE:

Android Studio 4.1.1
Build #AI-201.8743.12.41.6953283, built on November 5, 2020
Runtime version: 1.8.0_242-release-1644-b01 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Windows 10 10.0

Android Virtual Devices:

Name: Pixel_2_API_28
CPU/ABI: Google Play Intel Atom (x86)
Path: C:\Users\86188\.android\avd\Pixel_2_API_28.avd
Target: google_apis_playstore [Google Play] (API level 28)
Skin: pixel_2
SD Card: 512M
fastboot.chosenSnapshotFile: 
runtime.network.speed: full
hw.accelerometer: yes
hw.device.name: pixel_2
hw.lcd.width: 1080
hw.initialOrientation: Portrait
image.androidVersion.api: 28
tag.id: google_apis_playstore
hw.mainKeys: no
hw.camera.front: emulated
avd.ini.displayname: Pixel 2 API 28
hw.gpu.mode: auto
hw.ramSize: 1536
PlayStore.enabled: true
fastboot.forceColdBoot: no
hw.cpu.ncore: 4
hw.keyboard: yes
hw.sensors.proximity: yes
hw.dPad: no
hw.lcd.height: 1920
vm.heapSize: 256
skin.dynamic: yes
hw.device.manufacturer: Google
hw.gps: yes
hw.audioInput: yes
image.sysdir.1: system-images\android-28\google_apis_playstore\x86\
showDeviceFrame: yes
hw.camera.back: virtualscene
AvdId: Pixel_2_API_28
hw.lcd.density: 420
hw.arc: false
hw.device.hash2: MD5:55acbc835978f326788ed66a5cd4c9a7
fastboot.forceChosenSnapshotBoot: no
fastboot.forceFastBoot: yes
hw.trackBall: no
hw.battery: yes
hw.sdCard: yes
tag.display: Google Play
runtime.network.latency: none
disk.dataPartition.size: 6442450944
hw.sensors.orientation: yes
avd.ini.encoding: UTF-8
hw.gpu.enabled: yes

注意:以下示例仅在安卓虚拟设备上运行测试,并没有在真实的设备上运行测试。

项目

  • 方法 getPreferences(Context.MODE_PRIVATE) 返回的对象可以用于存储 Ativity 范围的数据;
  • 方法 getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE) 返回的对象可以用于存储应用范围的数据。

效果:

在这里插入图片描述

新建项目,选择 Empty Activity,在配置项目时,Minimum SDK 选择 API 16: Android 4.1 (Jelly Bean)

新建 Empty Activity,命名 SecondaryActivity

编辑 src\main\res\layout\activity_secondary.xml 布局文件,添加如下组件:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SecondaryActivity">

    <EditText
        android:id="@+id/editTextForActivity"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="针对 Activity 范围:2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/buttonStoreForActivity"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:text="Store For Activity"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editTextForActivity" />

    <Button
        android:id="@+id/buttonRetrieveForActivity"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:text="Retrieve For Activity"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/buttonStoreForActivity" />

    <View
        android:id="@+id/divider"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginTop="16dp"
        android:background="?android:attr/listDivider"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/buttonRetrieveForActivity" />

    <EditText
        android:id="@+id/editTextForApp"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="针对应用范围:2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/divider" />

    <Button
        android:id="@+id/buttonStoreForApp"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:text="Store For App"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editTextForApp" />

    <Button
        android:id="@+id/buttonRetrieveForApp"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:text="Retrieve For App"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/buttonStoreForApp" />
</androidx.constraintlayout.widget.ConstraintLayout>

编辑 SecondaryActivity

package com.mk;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import com.google.android.material.snackbar.Snackbar;

public class SecondaryActivity extends AppCompatActivity {

    private static final String TAG = "SecondaryActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_secondary);

        // 用于存储 Activity 范围的数据
        SharedPreferences preferences = getPreferences(Context.MODE_PRIVATE);

        ((Button) findViewById(R.id.buttonStoreForActivity)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = ((EditText) findViewById(R.id.editTextForActivity)).getText().toString();

                SharedPreferences.Editor editor = preferences.edit();
                editor.putString(MainActivity.KEY_NAME, name);
                editor.apply();
            }
        });

        ((Button) findViewById(R.id.buttonRetrieveForActivity)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = preferences.getString(MainActivity.KEY_NAME, null);

                Snackbar.make(v, name, Snackbar.LENGTH_LONG).setAction("Action", null).show();
            }
        });

        // 用于存储应用范围的数据
        SharedPreferences sharedPreferences = getSharedPreferences(MainActivity.FILE_NAME, Context.MODE_PRIVATE);

        ((Button) findViewById(R.id.buttonStoreForApp)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = ((EditText) findViewById(R.id.editTextForApp)).getText().toString();

                SharedPreferences.Editor editor = sharedPreferences.edit();
                editor.putString(MainActivity.KEY_NAME, name);
                editor.apply();
            }
        });

        ((Button) findViewById(R.id.buttonRetrieveForApp)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = sharedPreferences.getString(MainActivity.KEY_NAME, null);

                Snackbar.make(v, name, Snackbar.LENGTH_LONG).setAction("Action", null).show();
            }
        });
    }
}

编辑 src\main\res\layout\activity_main.xml 布局文件,添加如下组件:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/editTextForActivity"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="针对 Activity 范围:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/buttonStoreForActivity"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:text="Store For Activity"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editTextForActivity" />

    <Button
        android:id="@+id/buttonRetrieveForActivity"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:text="Retrieve For Activity"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/buttonStoreForActivity" />

    <View
        android:id="@+id/divider"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginTop="16dp"
        android:background="?android:attr/listDivider"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/buttonRetrieveForActivity" />

    <EditText
        android:id="@+id/editTextForApp"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="针对应用范围:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/divider" />

    <Button
        android:id="@+id/buttonStoreForApp"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:text="Store For App"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editTextForApp" />

    <Button
        android:id="@+id/buttonRetrieveForApp"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:text="Retrieve For App"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/buttonStoreForApp" />

    <View
        android:id="@+id/divider2"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:background="?android:attr/listDivider"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/buttonRetrieveForApp" />

    <Button
        android:id="@+id/buttonToSecondary"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginRight="16dp"
        android:text="To Secondary Activity"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/divider2" />
</androidx.constraintlayout.widget.ConstraintLayout>

编辑 MainActivity

package com.mk;

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

import androidx.appcompat.app.AppCompatActivity;

import com.google.android.material.snackbar.Snackbar;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    public static final String FILE_NAME = "com.mk";

    public static final String KEY_NAME = "name";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 用于存储 Activity 范围的数据
        SharedPreferences preferences = getPreferences(Context.MODE_PRIVATE);

        ((Button) findViewById(R.id.buttonStoreForActivity)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = ((EditText) findViewById(R.id.editTextForActivity)).getText().toString();

                SharedPreferences.Editor editor = preferences.edit();
                editor.putString(KEY_NAME, name);
                editor.apply();
            }
        });

        ((Button) findViewById(R.id.buttonRetrieveForActivity)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = preferences.getString(KEY_NAME, null);

                Snackbar.make(v, name, Snackbar.LENGTH_LONG).setAction("Action", null).show();
            }
        });

        // 用于存储应用范围的数据
        SharedPreferences sharedPreferences = getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);

        ((Button) findViewById(R.id.buttonStoreForApp)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = ((EditText) findViewById(R.id.editTextForApp)).getText().toString();

                SharedPreferences.Editor editor = sharedPreferences.edit();
                editor.putString(KEY_NAME, name);
                editor.apply();
            }
        });

        ((Button) findViewById(R.id.buttonRetrieveForApp)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = sharedPreferences.getString(KEY_NAME, null);

                Snackbar.make(v, name, Snackbar.LENGTH_LONG).setAction("Action", null).show();
            }
        });


        ((Button) findViewById(R.id.buttonToSecondary)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(SecondaryActivity.class);
            }
        });
    }

    private void startActivity(Class<?> cls) {
        startActivity(new Intent(this, cls));
    }
}

参考

Save key-value data

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值