Android数据存储系列————SharedPreferences

目录

前言

要点代码

示例代码

commit()和apply()的异同点

前言

  介绍:SharedPreferences是一个轻量型的数据存储,一般用于存储用户的用户信息如账号,密码,是Android自带的一个本地存储。

  主要作用:实现记住密码和自动登录功能

  存储形式:以xml文件形式存储

  存储位置:/data/data/包名/shared_prefs文件下【这个可以根据File Explorer查看,这里不做说明】

  操作流程:

  • 创建SharedPreferences对象
  • 保存数据

要点:SharedPreferences只支持Java的基本数据类型

要点代码:

1、创建SharedPreferences对象

private SharedPreferences sharedPreferences;
/**
 * 参数1:文件信息存放文件
 * 参数2:操作模式MODE_PRIVATE:私有模式,新内容覆盖原内容
*/
sharedPreferences=getSharedPreferences("userInfo",MODE_PRIVATE);

 

 

 操作模式介绍:

  • MODE_PRIVATE:默认模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容
  • MODE_WORLD_READABLE:允许其他应用读取这个模式创建的文件。在Android N上使用该模式将抛出SecurityException异常。【这个弃用了,不要问怎么知道了,知道的时候已经是泪了】
  • MODE_WORLD_WRITEABLE:允许其他应用写入这个模式创建的文件。在Android N上使用该模式将抛出SecurityException异常。【这个弃用了,不要问怎么知道了,知道的时候已经是泪了】
  • MODE_APPEND:如果文件已经存在了,则在文件的尾部添加数据。【这个没用过】
  • MODE_MULTI_PROCESS:SharedPreferences加载标志,当设置了该标志,则在磁盘上的文件将会被检查是否修改了,尽管SharedPreferences实例已经在该进程中被加载了。【这个没用过,看其他博主推荐使用ContentProvider】

 2、保存数据

第一步:创建一个SharedPreferences.Editor类的对象

SharedPreferences.Editor editor = sharedPreferences.edit();

 

第二步:通过SharedPreferences.Editor类的对象修改数据,不同的数据类型有不同的修改数据方法如,putString,putInt,putLong等方法,所有的方法都是一个参数是键的名称,第二个参数是键的值

editor.putBoolean("ISCHECK", true);

 

第三步:数据输入好后需要提交才能保存数据,调用方法commit()或者apply();【两者的区别

//方法一
editor.commit();
//方法二
editor.apply();

 

示例代码:

登录成功提示页布局代码【login.xml]

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:text="登录成功"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>

 

用户登录布局代码【main.xml】

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:text="账号:"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <EditText
        android:id="@+id/edit_account"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <TextView
        android:text="密码:"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <EditText
        android:id="@+id/edit_password"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <CheckBox
            android:text="记住密码"
            android:id="@+id/checkbox_rememberpass"
            android:layout_width="match_parent"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
        <CheckBox
            android:text="自动登录"
            android:id="@+id/checkbox_againlogin"
            android:layout_width="match_parent"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
        <Button
            android:text="登录"
            android:id="@+id/button_login"
            android:layout_width="match_parent"
            android:layout_weight="1"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</LinearLayout>

 

登录成功提示页Java代码【Login.java】

package com.hacker.exercise_sharedperference;

import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

public class Login extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.login);
    }
}

 

用户登录Java代码【MainActivity.java】

package com.hacker.exercise_sharedperference;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Toast;

/**
 * 目的:初步学习SharedPreferences
 * 结果:实现自动登录和记住密码
 */
public class MainActivity extends AppCompatActivity {
    //账号,密码
    private EditText account,password;
    //记住密码和自动登录
    private CheckBox rempass,agalogin;
    //登录
    private Button button;
    //用户名文本,密码文本
    private String userNameValue,passwordValue;
    //sharedPreferences,轻量型存储
    private SharedPreferences sharedPreferences;


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

        /**
         * 参数1:文件信息存放文件
         * 参数2:操作模式MODE_PRIVATE:私有模式,新内容覆盖原内容
         */
        sharedPreferences=getSharedPreferences("userInfo",MODE_PRIVATE);
        account=findViewById(R.id.edit_account);
        password=findViewById(R.id.edit_password);
        rempass=findViewById(R.id.checkbox_rememberpass);
        agalogin=findViewById(R.id.checkbox_againlogin);
        button=findViewById(R.id.button_login);

        //判断记住密码多选框的状态
        if(sharedPreferences.getBoolean("ISCHECK", false))
        {
            //设置默认是记录密码状态
            rempass.setChecked(true);
            account.setText(sharedPreferences.getString("USER_NAME", ""));
            password.setText(sharedPreferences.getString("PASSWORD", ""));
            //判断自动登陆多选框状态
            if(sharedPreferences.getBoolean("AUTO_ISCHECK", false))
            {
                //设置默认是自动登录状态
                agalogin.setChecked(true);
                //跳转界面
                Intent intent = new Intent(MainActivity.this,Login.class);
                MainActivity.this.startActivity(intent);

            }
        }

        // 登录监听事件  现在默认为用户名为:lin 密码:123
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("步骤2","1");
                userNameValue = account.getText().toString();
                passwordValue = password.getText().toString();

                if(userNameValue.equals("lin")&&passwordValue.equals("123"))
                {
                    Toast.makeText(MainActivity.this,"登录成功", Toast.LENGTH_SHORT).show();
                    //登录成功和记住密码框为选中状态才保存用户信息,即rempass.isChecked()为true时候进入if语句
                    if(rempass.isChecked())
                    {
                        //记住用户名、密码、
                        SharedPreferences.Editor editor = sharedPreferences.edit();
                        editor.putString("USER_NAME", userNameValue);
                        editor.putString("PASSWORD",passwordValue);
                        editor.apply();
                    }
                    //跳转界面
                    Intent intent = new Intent(MainActivity.this,Login.class);
                    MainActivity.this.startActivity(intent);
                }else{
                    Toast.makeText(MainActivity.this,"用户名或密码错误,请重新登录", Toast.LENGTH_LONG).show();
                }
            }
        });

        //监听记住密码多选框按钮事件
        rempass.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (rempass.isChecked()) {
                    SharedPreferences.Editor editor = sharedPreferences.edit();
                    editor.putBoolean("ISCHECK", true);
                    editor.apply();

                }else {
                    SharedPreferences.Editor editor = sharedPreferences.edit();
                    editor.putBoolean("ISCHECK", false);
                    editor.apply();
                }
            }
        });
        agalogin.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (agalogin.isChecked()) {
                    SharedPreferences.Editor editor = sharedPreferences.edit();
                    editor.putBoolean("AUTO_ISCHECK", true);
                    editor.apply();
                } else {
                    SharedPreferences.Editor editor = sharedPreferences.edit();
                    editor.putBoolean("AUTO_ISCHECK", false);
                    editor.apply();
                }
            }
        });
    }
    /**
     * 未优化时候,提示Skipped 33 frames!  The application may be doing too much work on its main thread.
     */
}

 

commit()和apply()的异同点:

commit()

        /**
         * Commit your preferences changes back from this Editor to the
         * {@link SharedPreferences} object it is editing.  This atomically
         * performs the requested modifications, replacing whatever is currently
         * in the SharedPreferences.
         *
         * <p>Note that when two editors are modifying preferences at the same
         * time, the last one to call commit wins.
         *
         * <p>If you don't care about the return value and you're
         * using this from your application's main thread, consider
         * using {@link #apply} instead.
         *
         * @return Returns true if the new values were successfully written
         * to persistent storage.
         */

 

apply()

/**
         * Commit your preferences changes back from this Editor to the
         * {@link SharedPreferences} object it is editing.  This atomically
         * performs the requested modifications, replacing whatever is currently
         * in the SharedPreferences.
         *
         * <p>Note that when two editors are modifying preferences at the same
         * time, the last one to call apply wins.
         *
         * <p>Unlike {@link #commit}, which writes its preferences out
         * to persistent storage synchronously, {@link #apply}
         * commits its changes to the in-memory
         * {@link SharedPreferences} immediately but starts an
         * asynchronous commit to disk and you won't be notified of
         * any failures.  If another editor on this
         * {@link SharedPreferences} does a regular {@link #commit}
         * while a {@link #apply} is still outstanding, the
         * {@link #commit} will block until all async commits are
         * completed as well as the commit itself.
         *
         * <p>As {@link SharedPreferences} instances are singletons within
         * a process, it's safe to replace any instance of {@link #commit} with
         * {@link #apply} if you were already ignoring the return value.
         *
         * <p>You don't need to worry about Android component
         * lifecycles and their interaction with <code>apply()</code>
         * writing to disk.  The framework makes sure in-flight disk
         * writes from <code>apply()</code> complete before switching
         * states.
         *
         * <p class='note'>The SharedPreferences.Editor interface
         * isn't expected to be implemented directly.  However, if you
         * previously did implement it and are now getting errors
         * about missing <code>apply()</code>, you can simply call
         * {@link #commit} from <code>apply()</code>.
         */

 

这上面的注释是SDK自带的对这两种的方法解释,总结一下

相同点

1、2个编辑器如果同时调用commit()方法或者apply()方法,那么最后一个调用这个方法的输入框(编辑器)将会获得值

2、2个方法都是一系列操作不可以被打断的方法,即原子操作

不同点

1、apply没有返回值,所以也就不知道是否提交成功;而commit方法会返回boolean表明修改是否提交成功

2、apply是将修改数据原子提交到内存,而后异步真正提交到硬件磁盘;而commit是同步的提交到硬件磁盘,

3、apply方法调用的情况实在状态切换的时候

Android建议

如果不需要返回值,且在主线程中调用,推荐使用apply方法。

posted on 2020-11-02 16:31  迷途行者  阅读(190)  评论(0编辑  收藏  举报

导航