第一行代码——第六章:数据存储全方案——详解持久化技术

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lhk147852369/article/details/84389698

目录:

6.1 持久化技术简介

6.2 文件存储

6.2.1 将数据存储到文件中

6.2.2 从文件中读出数据

6.3 SharedPreferences 存储

6.3.1 将数据存储到SharedPreferences中

6.3.2 从SharedPreferences 中读取数据

6.3.3 实现记住密码功能

6.4 SQLite数据库存储

6.4.1 创建数据库

6.4.2 升级数据库

6.4.3 添加数据

6.4.4 更新数据

6.4.5 删除数据

6.4.6 查询数据

6.4.7 使用SQL操作数据库

6.5 使用LitePal操作数据库

6.5.1 LitePal简介

6.5.2 配置LitePal

6.5.3 创建和升级数据库

6.5.4 使用LitePal添加数据

6.5.5 使用LitePal更新数据

6.5.6 使用LitePal删除数据

6.5.7 使用LitePal查询数据

6.6 小结与点评


知识点:

6.1 持久化技术简介

数据持久化是指将那些内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不会丢失。保存在内存中的数据是处于瞬时状态的,而保存在存储设备中的数据是处于持久状态的,持久化技术则是提供了一种机制可以让数据在瞬时状态和持久状态之间进行转换。

Android 系统主要提供了三种方式实现数据持久化功能 即文件存储、SharedPreference 存储以及数据库存储。当然,也可以将数据保存在手机的 SD 卡中,但相对会复杂一些,而且不安全。

6.2 文件存储

文件存储是 Android 中最基本的一种数据存储方式,它不对存储的内容进行任何的格式化处理,所有数据都是原封不动地保存到文件当中的,因而它比较适合用于存储一些简单的文本数据或二进制数据。

6.2.1 将数据存储到文件中

在这里,我们通过Context 类中提供了一个 openFileOutput () 方法,用于将数据存储到指定的文件中。

Context 类中还提供了一个 openFileInput() 方法,用于从文件中读取数据。

 private void save(String string) {
        String data = "Data to save";

        FileOutputStream fos = null;
        BufferedWriter writer = null;
        try {
            fos = openFileOutput("data", Context.MODE_PRIVATE);
            writer = new BufferedWriter(new OutputStreamWriter(fos));
            writer.write(string);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

6.2.2 从文件中读出数据

  private void load() {
        FileInputStream in = null;
        BufferedReader reader = null;
        StringBuilder content = new StringBuilder();
        try {
            in = openFileInput("data");
            reader = new BufferedReader(new InputStreamReader(in));
            String line = "";
            while ((line = reader.readLine()) != null) {
                content.append(line);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }

6.3 SharedPreferences 存储

不同于文件的存储方式,SharedPreferences 是使用键值对的方式来存储数据的。

获取SharedPreferences 对象

  • Context 类中的 getSharedPreferences()方法
      此方法接收两个参数,第一个参数指定 SharedPreferences 文件的名称,第二个参数指定操作模式,目前只有 MODE_PRIVATE 一种模式,和直接传入 0 效果相同。其他几种模式已被废弃。

  • Activity 类中的 getPreferences()方法
      此方法和上面的方法相似,但只接收一个操作模式参数,使用这个方法时会自动将当前活动的类名作为 SharedPreferences 的文件名。

  • PreferenceManager 类中的 getDefaultSharedPreferences()方法
      这是一个静态方法,它接收一个 Context 参数,并自动使用当前应用程序的包名作为前缀来命名 SharedPreferences 文件。

向sSharedPreferences 中存储内容

调用 SharedPreferences 对象的 edit()方法来获取一个 SharedPreferences.Editor 对象。
向 SharedPreferences.Editor 对象中添加数据,如添加一个布尔型数据使用 putBoolean 方法,添加一个字符串使用 putString()方法,以此类推。
调用 apply()方法将添加的数据提交,完成数据存储。

6.3.1 将数据存储到SharedPreferences中

    SharedPreferences.Editor sp = getSharedPreferences("data", MODE_PRIVATE).edit();
        sp.putString("uid", "1");
        sp.apply();

6.3.2 从SharedPreferences 中读取数据

//        SharedPreferences sp=getSharedPreferences("data", MODE_PRIVATE);
//        sp.getString()

6.3.3 实现记住密码功能

我们首先封装一下SharedPreferences

public class PrefUtils {

    private static final String PREF_NAME = "config";

    /**
     * 读取布尔数据
     * @param ctx 上下文
     * @param key 键
     * @param defaultValue 默认值
     * @return
     */
    public static boolean getBoolean(Context ctx, String key,
                                     boolean defaultValue) {
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        return sp.getBoolean(key, defaultValue);
    }

    /**
     * 添加布尔数据
     * @param ctx 上下文
     * @param key 键
     * @param value 添加的数据
     */
    public static void setBoolean(Context ctx, String key, boolean value) {
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        sp.edit().putBoolean(key, value).apply();
    }

    /**
     * 读取字符串
     * @param ctx
     * @param key
     * @param defaultValue
     * @return
     */
    public static String getString(Context ctx, String key, String defaultValue) {
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        return sp.getString(key, defaultValue);
    }

    /**
     * 添加字符串
     * @param ctx
     * @param key
     * @param value
     */
    public static void setString(Context ctx, String key, String value) {
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        sp.edit().putString(key, value).apply();
    }

    /**
     * 读取int类型数据
     * @param ctx
     * @param key
     * @param defaultValue
     * @return
     */
    public static int getInt(Context ctx, String key, int defaultValue) {
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        return sp.getInt(key, defaultValue);
    }

    /**
     * 添加int类型数据
     * @param ctx
     * @param key
     * @param value
     */
    public static void setInt(Context ctx, String key, int value){
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        sp.edit().putInt(key, value).apply();
    }

    /**
     * 将数据全部清除掉
     * @param ctx
     */
    public static void clear(Context ctx){
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        sp.edit().clear().apply();
    }
}

然后来编辑下登录界面,修改 activity_login.xml 中的代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!--***************** 账号 *********************-->
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="60dp">
        <TextView
            android:layout_width="90dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:gravity="center"
            android:textSize="18sp"
            android:text="账号:"/>

        <EditText
            android:id="@+id/et_account"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_gravity="center_vertical"/>
    </LinearLayout>

    <!--***************** 密码 *********************-->
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="60dp">
        <TextView
            android:layout_width="90dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:gravity="center"
            android:textSize="18sp"
            android:text="密码:"/>

        <EditText
            android:id="@+id/et_password"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_gravity="center_vertical"
            android:inputType="textPassword"/>
    </LinearLayout>

    <!--***************** 是否记住密码 *********************-->
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <CheckBox
            android:id="@+id/cb_remember_pass"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:layout_gravity="center_vertical"
            android:text="记住密码"/>

    </LinearLayout>

    <Button
        android:id="@+id/btn_login"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_margin="10dp"
        android:text="登录"/>

</LinearLayout>

只是添加了个 CheckBox 来勾选记住密码,接着修改 LoginActivity 的代码,如下:

public class LoginActivity extends BaseActivity {

    private EditText et_account, et_password;
    private CheckBox cb_remember_pass;
    private Button btn_login;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        et_account = (EditText) findViewById(R.id.et_account);
        et_password = (EditText) findViewById(R.id.et_password);
        cb_remember_pass = (CheckBox) findViewById(R.id.cb_remember_pass);
        btn_login = (Button) findViewById(R.id.btn_login);
        
        Boolean isRemember = PrefUtils.getBoolean(this,"remember_pass",false);
        if (isRemember){
            // 将账号和密码都设置到文本框中
            String account = PrefUtils.getString(this,"account","");
            String password = PrefUtils.getString(this,"password","");
            et_account.setText(account);
            et_password.setText(password);
            cb_remember_pass.setChecked(true);
        }

        btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String account = et_account.getText().toString();
                String password = et_password.getText().toString();
                // 若账号是 wonderful 且密码是 123456,就认为登录成功
                if (account.equals("wonderful") && password.equals("123456")){
                    // 检查复选框是否被勾选
                    if (cb_remember_pass.isChecked()){
                        // 保存数据到SharePreference文件中
                        PrefUtils.setBoolean(LoginActivity.this,"remember_pass",true);
                        PrefUtils.setString(LoginActivity.this,"account",account);
                        PrefUtils.setString(LoginActivity.this,"password",password);
                    }else {
                        // 清除SharePreference文件中的数据
                        PrefUtils.clear(LoginActivity.this);
                    }
                    // 登录成功跳转到主界面
                    IntentUtils.myIntent(LoginActivity.this,ForceOfflineActivity.class);
                    finish();
                }else {
                    ToastUtils.showShort("账号或密码无效!");
                }
            }
        });

    }

    @Override
    protected int initLayoutId() {
        return R.layout.activity_login;
    }
}

具体代码就不解释了,看注释。

现在运行下程序,输入账号和密码并选中记住密码复选框后,点击登录,就会跳转到 ForceOfflineActivity。接着在 ForceOfflineActivity 中发出一条强制下线广播会让程序重新回到登录界面, 此时你会发现,账号密码都已经自动填充到界面上了,如下:

记住密码功能效果这样我们就使用 SharedPreferences 技术将记住密码功能成功实现了。当然这只是个简单的示例,实际项目中将密码以明文的形式存储在 SharedPreferences 文件中是不安全的,还需配合加密算法进行保护。

6.4 SQLite数据库存储

6.4.1 创建数据库

6.4.2 升级数据库

6.4.3 添加数据

6.4.4 更新数据

6.4.5 删除数据

6.4.6 查询数据

6.4.7 使用SQL操作数据库

以上关于SQLite内容 我单独写了一篇文章 请看:

https://blog.csdn.net/lhk147852369/article/details/83307384

6.5 使用LitePal操作数据库

6.5.1 LitePal简介

LitePal 是一款开源的 Android 数据库框架,它采用了对象关系映射(ORM)的模式,并将我们平时开发最常用到的一些数据库功能进行了封装,使得不用编写一行 SQL 语句就可以完成各种建表和增删查改的操作。LitePal 的项目主页上也有详细的使用文档,地址是:https://github.com/LitePalFramework/LitePal

6.5.2 配置LitePal

使用 LitePal 的第一步,在 app/build.gradle 文件中引入 LitePal 的最新版本:

compile 'org.litepal.android:core:1.4.1'

项目中引入 LitePal 成功后,需要配置 litepal.xml 文件。右击 app/src/main 目录→New→Directory,创建一个 assets 目录,然后在 assets 目录下再新建一个 litepal.xml 文件,接着编辑 litepal.xml 文件中的内容,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<litepal>
    <!-- 指定数据库名 -->
    <dbname value="MyBookStore"></dbname>

    <!-- 指定数据库版本号 -->
    <version value="1"></version>

    <!-- 指定所有的映射模型 -->
    <list>

    </list>
</litepal>

最后还要在 Application 中调用 LitePal 的初始化方法:

/**
 * 全局
 * Created by KXwon on 2016/12/9.
 */
public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        // 调用 LitePal 的初始化方法
        LitePal.initialize(this);
    }
}

当然别忘了在 AndroidManifest.xml 中配置 Application:

<application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    . . .
 </application>

现在 LitePal 的配置工作完成了,下面正式开始使用它吧。

6.5.3 创建和升级数据库

郭霖专栏:Android数据库高手秘籍(二)——创建表和LitePal的基本用法

https://blog.csdn.net/guolin_blog/article/details/38556989

6.5.4 使用LitePal添加数据

郭霖专栏:Android数据库高手秘籍(五)——LitePal的存储操作

https://blog.csdn.net/guolin_blog/article/details/39345833

6.5.5 使用LitePal更新数据

6.5.6 使用LitePal删除数据

郭霖专栏:Android数据库高手秘籍(六)——LitePal的修改和删除操作

https://blog.csdn.net/guolin_blog/article/details/40083685

6.5.7 使用LitePal查询数据

郭霖专栏:

https://blog.csdn.net/guolin_blog/article/details/40153833

6.6 小结与点评

郭霖总结:

经过了这一章漫长的学习,我们终于可以缓解一下疲劳,对本章所学的知识进行核现和总结了。本章主要是对Android常用的数据持久化方式进行了详细的讲解,包括文件存储器 SharedPreferences存储以及数据库存储。 其中文件适用于存储一-些简单的文本数据或者二进制数适用于存储些键值队 ,而数据库则适用于存储那些复杂的关系型数据。虽然目前你已经掌握了这3种数据持久化方式的用法,但是能够根据项目的实际需求来选择最合适的方式也是你未来需要继续探索的。

那么正如上一章小结里提到的,既然现在我们已经掌握了Anid中的数据持久化技术,接下来就应该继续学习 Adoid中剩余的四大组件了。放松下自己,然后一起踏上内容提供器的学习之旅吧。

我的总结:

存储这一方面也是比较重要的,经过了这章内容的学习,我的能力又有了很大的进步,对于java中的Sterm流 相关的内容 也有了更多的了解。

猜你喜欢

转载自blog.csdn.net/lhk147852369/article/details/84389698