Android学习笔记14 数据存储全攻略

作者: RumbleTsc | 来源:发表于2016-07-24 12:47 被阅读413次

    这是Android学习笔记的第14篇,之前关于界面方面的学习总结暂时告一段落。这篇主要详细介绍Android开发过程中数据存储的常见几种方式。

    一、概述
    二、Shared Preferences 简单键值对
    三、Internal Storage 内部存储
    四、External Storage 外部存储
    五、SQLite数据库
    六、Network Connection 网络存储
    七、总结
    

    一、概述

    在平常的应用开发中,数据存储应该是我们经常要接触的内容,同时也是相当重要的部分。例如,要开发一个课程表的App,如果用户将自己的课程数据输入,但是下次登录时却看不到之前的数据,那这样的App还有价值吗,我们需要采取某种方式把数据存储下来。Android为我们的数据存储提供了很多选择,根据不同的存储需要,可以采取不同的方式。

    总的来说,数据存储有两种类别,一种是存储在本地,另一种是通过网络把数据存储在服务器端。本文主要介绍数据在本地存储的4种基本方式,包括Shared Preferences(简单键值对存储),Internal Storage (内部存储),External Storage (外部存储),SQLite数据库。

    二、Shared Preferences 简单键值对

    1、概述

    Shared Preferences,直译就是共用的配置信息,它的使用很简单,主要是采用键值对的形式来保存应用的一些常用配置等少量的数据,且这些数据的格式非常简单。例如,用户登录时提供一个选择按钮,询问是否记住密码,这时就可以使用这种方式。

    2、例子

    Shared Preferences平时在使用过程中比较简单,经常用到的有两个类接口,SharedPreferences和SharedPreferences.Editor。其中,后面的SharedPreferences.Editor主要是用于修改数据。下面以一个例子来讲下它的用法。

    1、下图是个用户登录界面,输入用户名和密码后登录前可以选择是否记住密码,如果记住了,那么下次登录的时候EditText里就直接显示上次的用户名和密码。

    登录界面

    2、布局文件layout_preferences.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        android:padding="8dp">
    
        <EditText
            android:id="@+id/et_username"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="用户名">
    
            <requestFocus />
        </EditText>
    
        <EditText
            android:id="@+id/et_userpasswd"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="密码" />
    
        <CheckBox
            android:id="@+id/cb_keep"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="记住密码" />
    
        <Button
            android:id="@+id/btn_login"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:text="登录" />
    </LinearLayout>
    

    3、Activity里的代码SharedPreActivity 。

    public class SharedPreActivity extends Activity {
    
        SharedPreferences sp;
        SharedPreferences.Editor spEditor;
    
        private static final String FILE_USER = "FILE_USER_LO";
        private static final String KEY_KEEP = "keeppswd";
        private static final String KEY_USERNAME = "username";
        private static final String KEY_USERPASSWD = "userpswd";
    
        private EditText etUserName, etUserPasswd;
        private Button btnLogin;
        private CheckBox cbKeep;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.layout_preferences);
    
            initView();
            initData();
        }
    
        private void initView() {
            etUserName = (EditText) findViewById(R.id.et_username);
            etUserPasswd = (EditText) findViewById(R.id.et_userpasswd);
            cbKeep = (CheckBox) findViewById(R.id.cb_keep);
            btnLogin = (Button) findViewById(R.id.btn_login);
        }
    
        //初始化数据
        private void initData() {
    
            sp = getSharedPreferences(FILE_USER, Context.MODE_PRIVATE);
    
            //获取之前是否点击了保存密码
            cbKeep.setChecked(sp.getBoolean(KEY_KEEP, false));
    
            //如果点击了就获取密码
            if (cbKeep.isChecked()) {
                etUserName.setText(sp.getString(KEY_USERNAME, ""));
                etUserPasswd.setText(sp.getString(KEY_USERPASSWD, ""));
            }
    
            btnLogin.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View view) {
    
                    String userName = etUserName.getText().toString().trim();
                    String userPasswd = etUserPasswd.getText().toString().trim();
    
                    if (cbKeep.isChecked()) {
                        funDataSave(userName, userPasswd, 1);
                    } else {
                        funDataSave(userName, userPasswd, 0);
                    }
                }
            });
        }
    
        private void funDataSave(String username, String userpassword, int type) {
    
            spEditor = sp.edit();
    
            if (type == 0) {
    
                spEditor.putBoolean(KEY_KEEP, false);
                spEditor.putString(KEY_USERNAME, "");
                spEditor.putString(KEY_USERPASSWD, "");
            } else {
                spEditor.putBoolean(KEY_KEEP, true);
                spEditor.putString(KEY_USERNAME, username);
                spEditor.putString(KEY_USERPASSWD, userpassword);
            }
            spEditor.apply();
        }
    }
    

    3、用法解析

    1. Shared Preferences使用过程中,接口SharedPreferences通过getSharedPreferences(String name, int mode)方法来实例化,其中name是配置文件名,mode是配置文件操作模式。我们这里传入Context.MODE_PRIVATE,表示该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容。操作模式还有MODE_WORLD_READABLE,表示当前文件可以被其他应用读取。
      MODE_WORLD_WRITEABLE,表示当前文件可以被其他应用写入
    2. Shared Preferences允许我们存储的数据主要有Boolean、String、Int、Float、Long等几种,如果要对数据进行操作,通过SharedPreferences.edit()实例化接口SharedPreferences.Editor,之后通过putFloat(String key, float value)等方法可以将指定键名的数据存储到配置文件里,通过getFloat(String key, float defValue)等可以获取到指定键名的数据。
    3. 对数据进行操作,必须要提交才能生效,可以选择commit()或者apply(),官方推荐采用apply(),因为这种方法是异步进行的。

    三、Internal Storage 内部存储

    1、概述

    Internal Storage,内部存储,主要是将数据文件保存到设备的内部存储中。

    2、用法与解析

    1. 将数据写入到指定文件
        /**
         * 写入数据到内部存储
         *
         * @param wData    数据
         * @param filename 写入到的文件
         */
        private void funInternalWrite(String wData, String filename) {
    
            FileOutputStream fos;
    
            try {
    
                fos = openFileOutput(filename, Context.MODE_PRIVATE);
                fos.write(wData.getBytes());
                fos.close();
    
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    1. 读取指定文件的内容
        private String funInternalRead(String filename) {
    
            String rData = "";
    
            try {
    
                FileInputStream fis = openFileInput(filename);
                byte[] bytes = new byte[fis.available()];
                fis.read(bytes);
                fis.close();
    
                rData = new String(bytes);
    
            } catch (IOException e) {
                e.printStackTrace();
            }
            return rData;
        }
    
    1. 其它有用的方法
      getFilesDir() 得到文件的绝对路径
      getDir() 在内部存储上创建目录,如果已经存在就打开。
      deleteFile() 删除指定文件
      fileList() 返回应用存储的文件列表

    四、External Storage 外部存储

    1、概述

    每个Android设备都支持一个共享的外部存储,可以允许你存储文件。它可能是一个可拆卸的SD卡,也可能是不能拆卸的。

    2、用法与解析

    • 添加权限
    • 检查外部存储是否可用
    • 外部存储操作
    1. 添加权限
    读写权限

    这里需要注意, WRITE_EXTERNAL_STORAGE其实包括了读写两个权限,如果只需要读可以只添加读权限。

    2、检查外部存储是否可用

        private static boolean isExternalStorageWritable() {
    
            String state = Environment.getExternalStorageState();
            if (Environment.MEDIA_MOUNTED.equals(state)) {
                return true;
            }
            return false;
        }
    

    3、数据写入外部存储指定文件。

    public static void funExternalWrite(String data, String filename) {
    
            FileOutputStream fos = null;
    
            File file = new File(Environment.getExternalStorageDirectory(), filename);
    
            if (isExternalStorageWritable()) {
    
                try {
    
                    fos = new FileOutputStream(file, true);
                    fos.write(data.getBytes());
    
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (fos != null) {
                        try {
                            fos.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    

    4、读取外部存储指定文件

        public static String funExternalRead(String filename) {
    
            FileInputStream fileInputStream = null;
    
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    
            File file = new File(Environment.getExternalStorageDirectory(), filename);
    
            if (isExternalStorageWritable()) {
    
                try {
    
                    fileInputStream = new FileInputStream(file);
                    int len = 0;
                    byte[] data = new byte[1024];
                    while ((len = fileInputStream.read(data)) != -1) {
                        byteArrayOutputStream.write(data, 0, len);
                    }
    
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (fileInputStream != null) {
                        try {
                            fileInputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            return new String(byteArrayOutputStream.toByteArray());
        }
    

    五、SQLite数据库

    Android provides full support for SQLite databases. Any databases you create will be accessible by name to any class in the application, but not outside the application.

    Android完全支持SQLite数据库,应用中的任何数据库都可以通过名称来访问,但是别的应用不可以,当然应用间的数据共享可以用Content Provider来实现。

    SQLite数据库使用的一般步骤有:

    1. 新建一个继承自SQLiteOpenHelper 的子类,在其中完成数据库的初始化操作,包括创建表等等。重写onCreate方法在里面完成数据表的创建,onUpdate是数据库更新时调用的。下面这张图是个简单的例子。


      SQLiteOpenHelper 类
    2. 对数据库进行操作前一般先获取一个SQLiteDatabase 对象,利用它我们可以完成对数据库表的操作,比如增删改查等等。下面这张图是一个对数据表执行删除操作的函数,应该比较清楚。


      数据库表删除指定记录

    SQLite数据库其实很强大,熟悉常见的sql语句,可以很简单地完成对数据库表的操作。

    六、Network Connection 网络存储

    网络存储主要是把数据存储到服务器端,这部分内容我会在以后的博客中继续更新,欢迎大家继续关注。

    七、总结

    应用中数据存储的常见几种方式就是以上这些,内容提供者Content Provider的使用过程中通常会用到SQLite数据库,这个部分的内容大家可以看我之前的第3篇文章。最后,关于数据存储方式部分的使用,稍后会贴出源码链接。

    相关文章

      网友评论

      本文标题:Android学习笔记14 数据存储全攻略

      本文链接:https://www.haomeiwen.com/subject/hoprjttx.html