美文网首页
Android数据存储

Android数据存储

作者: shawXXQ | 来源:发表于2017-10-05 17:11 被阅读0次

SharedPreferences存储

采用键值对的方式将数据存储在一个XML文件中。
用途:主要用于保存应用内用户的一些偏好设置,如应用的音量等等。

数据存储过程

存数据

①获取SharedPreferences对象,有三种方式:

        /**
         * 第一个参数为文件名称
         * 第二个参数为操作模式,常用的为MODE_PRIVATE,表示只有当前应用程序才可以对这个文件进行读写
         */
        sharedPreferences = getSharedPreferences("test", MODE_PRIVATE);
        
        /**
         * 只接收一个操作模式参数
         * 默认将当前活动的类名作为文件名
         */
        sharedPreferences = getPreferences(MODE_PRIVATE);
        
        /**
         * 参数为上下文对象
         * 使用当前应用程序的包名作为前缀来命名文件
         */
        sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

②调用SharedPreferences对象的edit()方法得到SharedPreferences.Editor对象

        SharedPreferences.Editor editor = sharedPreferences.edit();

③向SharedPreferences.Editor对象采用键值对的形式添加数据

        editor.putString("name", "shaw");
        editor.putInt("age", 21);
        editor.putBoolean("student", true);

前三步常用的写法为:

        SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();

④调用apply()方法提交数据

        editor.apply();

取数据

①获取SharedPreferences对象
②调用SharedPreferences对象的getString()、getInt()等方法读取数据

        /**
         * 第一个参数为对应的键
         * 第二个参数为找不到键对应的值时的默认返回值
         */
        sharedPreferences.getString("name", "");
        sharedPreferences.getInt("age", 0);
        sharedPreferences.getBoolean("student", false);

文件存储

内部存储

内部存储即存储在应用程序内部,且文件默认是只能被当前应用所访问的,当卸载应用的时候,对应的内部存储的文件也会被删除。SharedPreferences和SQLite数据库都是存储在内部存储空间上的。

    /**
     * 保存内部存储中的内容
     * 内部存储不需要声明权限
     * 使用openFileOutput来打开一个输出流
     */
    public void saveInner() {
        FileOutputStream fos = null;
        String input = inner_et.getText().toString();
        try {
            fos = openFileOutput("inner.txt", MODE_PRIVATE);
            fos.write(input.getBytes());
            Toast.makeText(this, "保存到内部存储文件完成", Toast.LENGTH_SHORT).show();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    //关闭流
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 读取内部存储中的内容
     * 使用openFileInput来打开一个输入流
     */
    public void showInner() {
        FileInputStream fis = null;
        try {
            fis = openFileInput("inner.txt");
            int len = 0;
            byte[] buf = new byte[1024];
            //只要还没读到文件末尾就一直读取
            while ((len = fis.read(buf)) != -1) {
                //将byte类型的数组转换为String类型显示
                Toast.makeText(this, "读取到了" + new String(buf, 0, len), Toast.LENGTH_SHORT).show();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

执行效果

GIF.gif

外部存储

外部存储并非特指sdcard,无论安卓手机上是否有可移动的sdcard,都存在着外部存储空间,因为访问可移动的sdcard或者手机的内置外部存储都是通过相同的api。当手机连接电脑时,电脑可识别的部分一定为外部存储空间。
使用外部存储时要先检验存储介质是否可用

       //判断当前sdcard是否可用
       if (state.equals(Environment.MEDIA_MOUNTED)) {
           Log.i("tag", "当前sdcard可用");
       } else if (state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
           Log.i("tag", "当前sdcard只有读取权限");
           flag = false;
       } else {
           Log.i("tag", "当前sdcard不可用");
           flag = false;
       }
   /**
     * 使用外部存储保存图片
     */
    public void saveImage() {
        BufferedOutputStream bos = null;
        BufferedInputStream bis = null;
        try {
            //获取sdcard根路径
            File sdPath = Environment.getExternalStorageDirectory();
            file = new File(sdPath, "test.jpg");
            //读取项目中的图片资源
            InputStream is = getResources().openRawResource(R.drawable.orange);
            OutputStream os = new FileOutputStream(file);
            //使用输入输出缓冲流进行读写操作
            bis = new BufferedInputStream(is);
            bos = new BufferedOutputStream(os);
            int len = 0;
            byte[] buf = new byte[1024];
            while ((len = bis.read(buf)) != -1) {
                //从0开始写到len
                bos.write(buf, 0, len);
                //刷新操作
                bos.flush();
            }
            Toast.makeText(this, "图片写入完成", Toast.LENGTH_SHORT).show();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流操作
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 显示图片
     */
    public void showImage() {
        //从文件中读取图片
        Bitmap bitmap = BitmapFactory.decodeFile(file.getPath());
        out_image.setImageBitmap(bitmap);
    }

对外部存储的操作需要添加权限

    <!--添加写入权限-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

若运行在Android6.0(API 23)及以上的系统中,需要添加动态权限处理

        //申请向外部存储写数据的权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
            }, 1);
GIF.gif

常用的缓存路径

        Log.d("tag", "路径1 " + this.getCacheDir());
        Log.d("tag", "路径2 " + this.getExternalCacheDir());
        Log.d("tag", "路径3 " + Environment.getDownloadCacheDirectory());
图片.png

路径1为内部存储缓存
路径2位外部存储缓存
路径3为根目录缓存


SQLite数据库存储

数据库创建

继承SQLiteOpenHelper类并重写onCreate()和onUpgrade()方法

public class MyDatabaseHelper extends SQLiteOpenHelper {
    private static final String CREATE_BOOK = "create table Book(" +
            "id integer primary key autoincrement," +
            "author text," +
            "price real," +
            "pages integer," +
            "name text)";

    private Context mContext;

    public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        mContext = context;
    }

    //数据库被创建时执行,只执行一次
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK);
        Toast.makeText(mContext, "Create succeed", Toast.LENGTH_SHORT).show();
    }

    //数据库版本更新时执行
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}
public class MainActivity extends AppCompatActivity {
    private MyDatabaseHelper dbHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /**
         * 第一个参数为context对象
         * 第二个参数为数据库名
         * 第三个参数为一个自定义的Cursor对象,一般都为null
         * 第四个参数为版本号
         * 实例化该对象后使用构造方法创建数据库
         */
        dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
        Button createDatabase = (Button) findViewById(R.id.create_database);
        Button addData = (Button) findViewById(R.id.add_data);
        //创建数据库
        createDatabase.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //数据库已存在则打开,否则创建
                dbHelper.getWritableDatabase();
            }
        });

插入数据

        /**
         * 向表中添加数据
         */
        addData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /**
                 * getWritableDatabase()返回一个可对数据库进行读写操作的对象,
                 * 当数据库不可写入时,将出现异常
                 *
                 * getReadableDatabase()返回一个可对数据库进行读写操作的对象,
                 * 当数据库不可写入时,返回的对象以只读的方式打开数据库
                 */
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                ContentValues values = new ContentValues();
                /**
                 * 开始装填第一条数据
                 */
                values.put("name", "The Da Vinci Code");
                values.put("author", "Dan Brown");
                values.put("pages", 454);
                values.put("price", 16.96);
                db.insert("Book", null, values);

更新数据

                SQLiteDatabase db = dbHelper.getWritableDatabase();
                ContentValues values = new ContentValues();
                values.put("price", 10.99);
                db.update("Book", values, "name=?", new String[]{"The Da Vinci Code"});

删除数据

                SQLiteDatabase db = dbHelper.getWritableDatabase();
                db.delete("Book", "pages>?", new String[]{"500"});

查询数据

                SQLiteDatabase db = dbHelper.getWritableDatabase();
                /**
                 * 第一个参数为表名
                 * 第二个参数指定查询的列名
                 * 第三个参数指定where约束条件
                 * 第四个参数为where中的占位符提供具体的值
                 * 第五个参数指定需要group by的列
                 * 第六个参数对group by后的结果进一步约束
                 * 第七个参数指定查询结果的排序方式,ASC由小到大,DESC由大到小
                 */
                Cursor cursor = db.query("Book", null, null, null, null, null, null);
                if (cursor.moveToFirst()) {
                    do {
                        //遍历Cursor对象
                        String name = cursor.getString(cursor.getColumnIndex("name"));
                        int pages = cursor.getInt(cursor.getColumnIndex("pages"));
                    } while (cursor.moveToNext());
                }
                cursor.close();

也可以使用SQL语句完成CRUD操作

                db.execSQL("insert into Book(name,author,pages,price) values(?,?,?,?)", new String[]{
                        "The Da Vinci Code", "Dan Browm", "454", "16.96"
                });
                db.execSQL("update Book set price=? where name=?", new String[]{
                        "10.99", "The Da Vinci Code"
                });
                db.execSQL("delete from Book where pages>?", new String[]{"500"});
                db.rawQuery("select * from Book", null);

即除了查询操作使用rawQuery()方法外,其他操作均使用execSQL()方法完成。


Sqlite数据库事务管理
为了保证数据库中的某些操作要么同时执行,要么同时不执行,需要添加数据库事务管理,

                db.beginTransaction();
                //具体的数据库操作逻辑
                db.setTransactionSuccessful();
                db.endTransaction();

相关文章

  • Android ContentProvider(一)

    Android数据存储(一) Android数据存储(二) Android数据存储(三) Android数据存储(...

  • Android数据存储

    Android数据存储 Android提供了5种方式存储数据 SharedPreferences它是Android...

  • day07

    Android的存储方式 使用SharedPreferences存储数据 文件存储数据 SQLite数据库存储数据...

  • SharedPreferences存储数据

    Android的存储方式 使用SharedPreferences存储数据文件存储数据SQLite数据库存储数据使用...

  • 面试相关之 Android(二)

    数据存储 1. Android 中提供哪些数据持久存储的方法?参考回答:Android 平台实现数据存储的常见几种...

  • SharePreferences 分析及正确使用姿势

    1.Android 常见数据存储方式 在 Android 中,常用数据存储方式通常有以下几类: 文件存储:将数据存...

  • Android数据存储(三)

    前面两篇文章Android数据存储(一)和Android数据存储(二)分别使用文件存储、SharedPrefere...

  • SharedPreference与文件存储

    Android常用数据存储方式有SharedPreferences存储数据(虽然还是属于内部存储)、文件存储(内部...

  • Android中的数据存储

    1. Android中有哪些数据存储方式? Android中的数据存储主要有以下5种方式: File:文件存储,通...

  • 06 Room组件架构原理解析

    前言 Android应用数据存储简单来说有这么几种:文件存储、SharePreference存储、SQLite数据...

网友评论

      本文标题:Android数据存储

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