Android数据存储基础

本文介绍了Android中的数据持久化,包括文件存储、SharedPreferences存储、SQLite数据库存储,以及第三方库LitePal的使用。文件存储允许简单文本或二进制数据的保存,SharedPreferences使用键值对存储,SQLite适合存储复杂关系型数据,而LitePal为数据库操作提供了一层封装。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

持久化技术就是将内存中的瞬时数据保存到存储设备中,保证在手机关机或某一应用程序关闭的时候,数据不会丢失。

 Android存储文件和数据的地方:

  1. RAM、ROM、内存(内部存储器)、
  2. APP程序里面(Assets,raw,res),
  3. SD卡(早期的安卓的可以插卡,现在的不支持了,但是有些 arm板 嵌入式方向的还是带卡槽的)
  4. 网络

      (参考dadachenchen的文章,原文:https://blog.youkuaiyun.com/dadachenchen/article/details/84347616)

  1. RAM、ROM 这些东西我们就别碰了,不然一大堆问题,Environment.getRootDirectory()  需要获取root权限,不合适
  2. 内存和SD卡  大家得理解  Environment.getExternalStorageState()  代表的是什么意思,不是插卡的SD卡,而是说你买了开发板、手机,厂家送你的存储地方(直接你得让他送你哈)。  这部分作为主要的存储路径,小数据和大数据都适用。
  3. SD卡,黑色那张卡,老古董,现在手机都没有了,不建议大家使用
  4. 网络,请求自己的服务器,读取数据,URI的方式,httpClient    post 和 get 两种请求数据的方式

Android中主要提供了3中数据持久化方式:

  1. 文件存储
  2. AharePrefernces存储
  3. SQLite数据库存储
  4. 保存于手机SD卡(不推荐)

在AS中查看模拟器文件存储的方式:

可以在侧边栏打开Device File Explorer选择相应的文件夹进入查看(一般为data/data/package name/files)

一:文件存储

Android中最基本的数据存储方式,它不对存储的任何东西进行任何格式化的处理,所有数据元丰不动的保存到文件中。因此适用于存储一些简单的文本数据或二进制数据。

利用Context中openFileOutput()方法,可以将数据存储到指定的文件中。

利用Context中openFileInput()方法,可以从指定文件中读取数据。

(所有文件默认存储到/data/data/<package name>/files目录下)

/*
    * 利用java IO流的形式完成对文件的存储(原样存储)
    * */
    
    /*
    *@author: banzh
    *@function: 从存储文件中恢复数据到TextView中,测试数据的保存
    *           默认从data/data/package name/files目录下恢复文件。
    *           所以openFileInput()方法只是默认提供files目录下的DATA文件即可
    *@time 2019/5/24 18:15
    **/
    private String load() {
        FileInputStream fileInputStream;
        BufferedReader reader = null;
        StringBuilder builder = new StringBuilder();
        try {
            fileInputStream = getActivity().openFileInput("DATA");
            reader = new BufferedReader(new InputStreamReader(fileInputStream));
            String line = "";
            while ((line = reader.readLine()) != null){
                builder.append(line);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (reader != null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return String.valueOf(builder);
    }

    /*
    *@author: banzh
    *@function: 利用java IO 流的形式保存数据(原样保存)
    *           数据默认保存到data/data/package name/files/DATA中
    *@time 2019/5/24 18:16
    **/
    private void save(String input) {
        FileOutputStream outputStream = null;
        BufferedWriter bufferedWriter = null;
        try {
            outputStream = getActivity().openFileOutput("DATA", Context.MODE_PRIVATE);
            bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
            bufferedWriter.write(input);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (bufferedWriter != null){
                try {
                    bufferedWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

二:SharedPreferences存储

SharedPreferences是利用键值对的形式来存储数据的,且支持不同的数据类型,在对数据操作(读取)的时候通过对应的键将其内容读取出来。

SharedPreferences的文件都是存放在/data/data/<package name>/shared——prefs/目录下。

获取SharedPreferences对象的方式:

  1. Context类中的getSharedPreferences()
  2. Activity类中的getPreferences()
  3. PreferenceManager类中的getDefaultSharedPreferences()
/*
         *@author: banzh
         *@function:在button的点击事件中存储EditText所输入的数据
         *@time 2019/5/24 18:39
         **/
        button_save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /*
                * 调用第三种方式实现SharedPreferences
                * */
                /*1.
                 *调用SharedPreferences对象的edit方法获取一个SharedPreferences.Editor对象
                 * */
                SharedPreferences.Editor editor = getActivity().getSharedPreferences("share_data", Context.MODE_PRIVATE).edit();
                /*2.
                 * 向SharedPreferences.Editor对象中添加数据
                 * */
                String input = editText.getText().toString();
                editor.putString("msg", input);
                /*3.
                 * 用apply()方法,将数据提交
                 * */
                editor.apply();
            }
        });

        /*
         *@author: banzh
         *@function:在button的点击事件中恢复数据
         *@time 2019/5/24 18:39
         **/
        button_retext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /*
                * 调用第一种方法实现SharedPreferences
                * */
                SharedPreferences preferences = getContext().getSharedPreferences("share_data", Context.MODE_PRIVATE);
                String msg = preferences.getString("msg", "无存储内容!");
                textView.setText(msg);
            }
        });

 

(从图中可以看出SharedPreferences是利用XML形式存储文件的)

三:SQLite数据库存储

SQLite是一款轻量级的关系型数据库,运行速度快,占用资源少。它不仅支持标准的SQL语法,而且遵循数据库的ACID事务。当需要存储大量复杂的关系型数据的时候,SQLite比前两种都更适合。

Android中提供了一个SQLiteOpenHelper帮助类,帮助管理数据库。它是一个抽象类,必须要自己实现类去继承它。

SQLiteOpenHelper的两个重要方法:

  • onCreate();
  • onUpgrade();

其他重要的实例方法:

  • getReadableDatabase();
  • getWritableDatabase();

这两个方法可以创建或打开一个现有的数据库,并返回一个可对数据库进行读写操作的对象。当数据库不可写入时,getReadableDatabase()返回的对象只能以读的方式去打开数据库。而getWritableDatabase();会报异常。

数据库文件会存放在data/data/package name/databases/目录下。

以下是对象实现,相关注册在代码中体现:

package com.example.myboring.bottombar.fragment;

import android.app.AlertDialog;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.example.myboring.R;
import com.example.myboring.database.MyDatabaseHelper;

import static android.content.ContentValues.TAG;

public class Fragment3 extends Fragment {
    View view;
    Button btn_editText;
    TextView textView;
    android.widget.ScrollView scrollView;
    Button button_save;
    Button button_update;
    Button button_delect;
    Button button_query;

    EditText edit_book_name;
    EditText edit_book_author;
    EditText edit_book_pages;
    EditText edit_book_price;

    String name;
    String author;
    String pages;
    String price;

    private MyDatabaseHelper dbHleper;
    private SQLiteDatabase db;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment3, container, false);
        initView();
        return view;
    }

    private void initView() {
        btn_editText = view.findViewById(R.id.btn_editText);
        textView = view.findViewById(R.id.textView);
        scrollView = view.findViewById(R.id.scrollView);
        button_save = view.findViewById(R.id.button_save);
        button_update = view.findViewById(R.id.button_update);
        button_delect = view.findViewById(R.id.button_delect);
        button_query = view.findViewById(R.id.button_query);

        //实例化MyDatabaseHelper的对象
        //可根据对数据库的改变然后将版本升级即可
        dbHleper = new MyDatabaseHelper(getContext(), "BookStore.db", null, 2);

        /*
        * 向数据库中静态保存数据的相应实现
        * */
        button_save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //完成BookStore.db数据库的创建,初始化版本号为一
                db = dbHleper.getWritableDatabase();

                /*
                 * 用insert语句,向数据库中添加数据
                 * 向ContentValues中添加每列相对应的数据,
                 *
                 * "create table Book ("
                 *+ "id integer primary key autoincrement,"
                 *+ "author text,"
                 *+ "price real,"
                 *+ "pages integer,"
                 *+ "name text)";
                 * */

                /*
                 * 若中文存储会出现乱码问题:
                 * String s = "三国演义";
                 * String utf8Str = new String(s.getBytes("utf-8"), "utf-8);
                 * */
                ContentValues values = new ContentValues();
                values.put("name", "西游记");
                values.put("author", "第一个人");
                values.put("price", 100);
                values.put("pages", 9999);

                //完成数据的添加之后,用insert语句完成数据库的添加
                db.insert("Book", null, values);

                //清楚values的值,然后开始添加第二条数据

                values.clear();
                values.put("name", "三国演义");
                values.put("author", "第二个人");
                values.put("price", 1000);
                values.put("pages", 10000);
                db.insert("Book", null, values);

                Log.d(TAG, "button_save-->onClick:<<<<<<< " + "数据添加完成!!!");
            }
        });

        /*
        * 更新数据库的代码实现
        * */
        button_update.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                db = dbHleper.getWritableDatabase();
                ContentValues values = new ContentValues();
                values.put("price", 0.1111);
                db.update("Book", values, "name = ?",
                        new String[]{
                                "西游记"
                        });
            }
        });

        button_delect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                db = dbHleper.getWritableDatabase();
                db.delete("Book", "pages > ?",
                        new String[]{
                                "100"
                        });
            textView.setText("");
            }
        });

        /*
        * 查询数据库的代码实现
        * */
        button_query.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                db = dbHleper.getWritableDatabase();
                //查询表中现存的所有数据
                Cursor cursor = (Cursor) db.query("Book", null, null, null, null, null, null);
                if (cursor.moveToFirst()) {
                    do {
                        //遍历cursor对象,取出数据并输出
                        String name = cursor.getString(cursor.getColumnIndex("name"));
                        String author = cursor.getString(cursor.getColumnIndex("author"));
                        int price = cursor.getInt(cursor.getColumnIndex("price"));
                        int pages = cursor.getInt(cursor.getColumnIndex("pages"));

                        String data = "+++++++++++++++++++++++++++++ \n" +
                                "书名:" + name + "\n" +
                                "作者: " + author + "\n" +
                                "书页: " + pages + "\n" +
                                "价格: " + price + "\n"
                                + "+++++++++++++++++++++++++++++ \n\n";
                        textView.append(data);
                    } while (cursor.moveToNext());
                }
                cursor.close();
            }
        });

        /*
        * 利用对话框功能动态的添加书籍信息,原理同静态保存数据的方法
        * 此代码中对话框的功能实现值得仔细研究
        * */
        btn_editText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
                LayoutInflater inflater = LayoutInflater.from(getContext());
                View ADview = inflater.inflate(R.layout.editbook, null);

                builder.setTitle("请输入书籍信息:");
                builder.setMessage("在这里你可以添加相信的图书资源到数据库中!");
                builder.setView(ADview);
                builder.setPositiveButton("添加", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        db = dbHleper.getWritableDatabase();

                        ContentValues values = new ContentValues();

                        name = edit_book_name.getText().toString().trim();
                        author = edit_book_author.getText().toString().trim();
                        pages = edit_book_pages.getText().toString().trim();
                        price = edit_book_price.getText().toString().trim();

                        values.put("name", name);
                        values.put("author", author);
                        values.put("price", new Integer(pages));
                        values.put("pages", new Integer(price));

                        db.insert("Book", null, values);

                        dialog.dismiss();
                    }
                });

                /*
                * 调用setView方法只会标题和按钮之间的内容:
                * ((AlertDialog) dialog).setView(ADview);
                *
                * 而调用setContentView方法则会覆盖整体的View:
                * dialog.setContentView();
                * */
                AlertDialog dialog = builder.create();
                dialog.show();
                edit_book_name = dialog.findViewById(R.id.edit_book_name);
                edit_book_author = dialog.findViewById(R.id.edit_book_author);
                edit_book_pages = dialog.findViewById(R.id.edit_book_pages);
                edit_book_price = dialog.findViewById(R.id.edit_book_price);

                /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    new AlertDialog.Builder(getContext())
                            .setTitle("添加书籍信息")
                            .setMessage("一本书的销售信息")
                            .setView(R.layout.editbook)
                            .setPositiveButton("添加", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    db = dbHleper.getWritableDatabase();

                                    ContentValues values = new ContentValues();

                                    values.put("name", name);
                                    values.put("author", author);
                                    values.put("price", new Integer(pages));
                                    values.put("pages", new Integer(price));

                                    db.insert("Book", null, values);
                                    Log.d(TAG, "button_save-->onClick:<<<<<<< " + "数据添加完成!!!");
                                }
                            }).show();
                    name = edit_book_name.getText().toString().trim();
                    author = edit_book_author.getText().toString().trim();
                    pages = edit_book_pages.getText().toString().trim();
                    price = edit_book_price.getText().toString().trim();
                }*/
            }
        });
    }

    /*
    * 废掉的代码
    * */
    private void addBook() {
        db = dbHleper.getWritableDatabase();

        ContentValues values = new ContentValues();

        String name = edit_book_name.getText().toString().trim();
        String author = edit_book_author.getText().toString().trim();
        String pages = edit_book_pages.getText().toString().trim();
        String price = edit_book_price.getText().toString().trim();

        values.put("name", name);
        values.put("author", author);
        values.put("price", new Integer(pages));
        values.put("pages", new Integer(price));

        db.insert("Book", null, values);
        Log.d(TAG, "button_save-->onClick:<<<<<<< " + "数据添加完成!!!");
    }
    /*
     * 废掉的代码
     * */
}

四:LitePal的使用

开源库LitePal是一款Android数据库框架,实现了对数据库操作的有一层封装。配置LitePal的方法不在累赘。

具体的信息请参照https://github.com/LitePalFramework/LitePal(LitePal主页)

代码如下:

package com.example.myboring.bottombar.fragment;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.example.myboring.R;
import com.example.myboring.database.Person;

import org.litepal.LitePal;
import org.litepal.crud.LitePalSupport;

import java.util.List;

public class Fragment4 extends Fragment {

    View view;
    EditText editText;
    TextView textView;
    Button create_db;
    Button save_db, update_db, delete_db, query_db;

    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment4, container, false);
        initView();
        return view;
    }

    private void initView() {
        create_db = view.findViewById(R.id.create_db);
        save_db = view.findViewById(R.id.save_db);
        update_db = view.findViewById(R.id.update_db);
        delete_db = view.findViewById(R.id.delete_db);
        query_db = view.findViewById(R.id.query_db);
        textView = view.findViewById(R.id.textView);
        initOther();
    }

    private void initOther() {
        create_db.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                LitePal.getDatabase();
            }
        });

        save_db.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /*private double height;
                private String name;
                private String sex;
                private String address;*/
                Person person = new Person();
                person.setHeight(180.00);
                person.setName("bai");
                person.setSex("男");
                person.setAddress("中国西安");

                person.save();
            }
        });

        update_db.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Person person_1 = new Person();
                person_1.setAddress("中国美国");
                person_1.setName("zai");
                person_1.setHeight(111);
                person_1.setSex("女");

                person_1.save();

                person_1.setHeight(200);
                person_1.updateAll("name = ? ", "zai");

                /*
                不推荐使用这种方法更新数据
                person_1.setHeight(167);
                person_1.save();*/
            }
        });

        delete_db.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                LitePal.deleteAll(Person.class, "height < ?", "220");
                textView.setText("");
            }
        });

        query_db.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                List<Person> list_person = LitePal.findAll(Person.class);
                for (Person person : list_person) {
                    String msg = "++++++++++++++++++\n"
                            + "姓名: " + person.getName() + "\n"
                            + "性别: " + person.getSex() + "\n"
                            + "身高: " + person.getHeight() + "\n"
                            + "地址: " + person.getAddress() + "\n"
                            + "++++++++++++++++++\n\n";

                    textView.append(msg);
                }
            }
        });
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值