Android中数据存储

数据存储

Android中提供了五种主要的数据存储方式,分别为文件存储,SharedPreferences存储,SQLite数据库存储,ContentProvider存储,网络存储。主要整理文件存储,SharedPreferences存储,SQLite数据库存储,Litepal,序列化知识点及应用

文件存储

  • Android的文件存储主要分为内部存储和外部存储两部分
  • 在Android中,文件存储的读写主要通过Java的IO流体系来实现。Android还提供了Context类中的openFileInput()openFileOutput()方法来简化文件的读写操作。
  • 故可以分为四个板块解析文件存储,分别是:将数据写入内部存储文件中,读取内部存储文件中的数据。将数据写入外部存储文件中,读取外部存储文件中的数据

内部存储

  1. 存储路径:内部存储是是将应用中的数据以文件存储的方式存储在应用中,内部存储的路径通常是/data/data/<包名>/files
  2. 私有化:每个应用都有自己的私有内部存储空间,其他应用无法直接访问,如有需要访问需申请权限
  3. 自动清理:当应用被卸载时,内部存储中的文件也会被一并删除。
  4. 适用范围:适用于存储应用的私有数据,如配置文件、数据库、缓存等。这些数据通常不需要与其他应用共享,且当应用被卸载时,这些数据也需要被一并删除。
将数据写入内部存储文件中
  1. 使用了ContextopenFileOutput()方法来创建或打开文件,并返回一个FileOutputStream对象。
  • 通过Context提供的openFileOutput(String name, int mode))方法。

  • openFileOutput()方法用于打开应用对应的输出流,将数据存储在指定的文件中。

  • 参数name表示文件名,mode表示文件操作的方式。

注意:第二个参数是文件的操作模式,主要有两种模式可选,MODE_PRIVATE和 MODE_APPEND。

  • MODE_PRIVATE是默认的操作模式,表示该文件只能被当前程序读写
  • 而MODE_APPEND,则表示如果该文件已存在,就往文件里面追加内容,不存在就创建新文件。
  • 另外两种:MODE_WORLD_READABLE和 MODE_WORLD_WRITEABLE,这两种模式表示允许其他的应用程序对我们程序中的文件进行读写操作,不过由于这两种模式过于危险,很容易引起应用的安全性漏洞,已在 Android 4.2版本中被废弃。

2.使用write()方法将字符串转换为字节并写入文件。注意,这里使用了try-with-resources语句来自动关闭FileOutputStream

String fileName = "myfile.txt";  
String fileContents = "Hello";  
  
try {
FileOutputStream fos = openFileOutput(fileName, Context.MODE_PRIVATE);
    fos.write(fileContents.getBytes());  
} finally{
try{
	if(fos!=null){
		fos.close();//关闭输入流
}catch (IOException e) {  
    e.printStackTrace();  
	}
}

读取内部存储文件中的数据
  1. 这里使用了ContextopenFileInput()方法来获取文件的FileInputStream
  • openFileInput()方法用于打开应用对应的输入流,读取指定文件中的数据
  1. 然后通过InputStreamReaderBufferedReader来逐行读取文件内容。
StringBuilder stringBuilder = new StringBuilder();  
  
try (FileInputStream fis = openFileInput(fileName)) {  
    InputStreamReader inputStreamReader = new InputStreamReader(fis);  
    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
    String line;  
    while ((line = bufferedReader.readLine()) != null) {  
        stringBuilder.append(line);  
    }  
    Log.d("InternalStorage", "File content: " + stringBuilder.toString());  
} catch (IOException e) {  
    e.printStackTrace();  
}

外部存储

  1. 存储路径:将数据以文件的形式存储到一些外部设备(例如SD卡或者设备内嵌的存储卡)上,属于永久性存储方式。(外部存储的文件通常位于storage/emulated/O目录下)
  2. 共享性:外部存储的文件可以被其他应用程序共享,当将外部存储设备连接到计算机时,这些文件可以被浏览、修改和删除,因此这种方式不安全。
  3. 适用范围:适用于存储需要与其他应用共享或长期保存的数据,如图片、视频、音乐等。这些数据在应用卸载时不会被删除,且可以被其他应用访问。
  4. 申请权限:AndroidManifest.xml文件中已经声明了相应的权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
<!-- 对于Android 10及以上,建议使用分区存储(Scoped Storage),则不需要这个权限 -->
将数据写入外部存储文件中(这里以机身存储为例,SD卡类似)
String externalFilesDir = getExternalFilesDir(null).getAbsolutePath();  
File file = new File(externalFilesDir, "myfile_external.txt");  
String fileContents = "Hello, External Storage!";  
  
try (FileOutputStream fos = new FileOutputStream(file)) {  
    fos.write(fileContents.getBytes());  
    Log.d("ExternalStorage", "File written to external storage");  
} catch (IOException e) {  
    e.printStackTrace();  
}
读取外部存储文件中的数据
StringBuilder stringBuilder = new StringBuilder();  
  //这里假设file是一个指向外部存储中文件的File对象
try (FileInputStream fis = new FileInputStream(file)) {  
    InputStreamReader inputStreamReader = new InputStreamReader(fis);  
    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);  
    String line;  
    while ((line = bufferedReader.readLine()) != null) {  
        stringBuilder.append(line);  
    }  
    Log.d("ExternalStorage", "File content: " + stringBuilder.toString());  
} catch (IOException e) {  
    e.printStackTrace();  
}

SharedPreferences

  • SharedPreferences 是 Android 平台上一个轻量级的存储类,它允许你保存和读取应用程序的私有原始数据类型。
  • 主要用于存储少量的数据,如用户的设置、偏好等。
  • 以 XML 文件的形式保存在设备的内部存储中,文件名和路径由 Android 系统自动管理。

将数据存储在SharedPreferences

使用Context类中的getSharedPreferences()方法。

  • 其中getSharedPreferences()方法接收两个参数,第一个参数是文件名,第二个参数是操作模式,现主要是MODE_PRIVATE。

具体实现步骤:

  1. 调用SharedPreferences对象的edit()方法来获取一个SharedPreferences.Editor对象。

  2. 向 SharedPreferences.Editor对象中添加数据,比如添加一个布尔型数据就使用putBoolean()方法,添加一个字符串则使用putstring()方法,以此类推。

  3. 调用 apply()方法将添加的数据提交,从而完成数据存储操作。

 /**
     * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
     *
     * @param context 上下文
     * @param key     key值
     * @param object  value值
     */
    public static void put(Context context, String key, Object object) {

        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();

        if (object instanceof String) {
            editor.putString(key, (String) object);
        } else if (object instanceof Integer) {
            editor.putInt(key, (Integer) object);
        } else if (object instanceof Boolean) {
            editor.putBoolean(key, (Boolean) object);
        } else if (object instanceof Float) {
            editor.putFloat(key, (Float) object);
        } else if (object instanceof Long) {
            editor.putLong(key, (Long) object);
        } else {
            editor.putString(key, object.toString());
        }

        SharedPreferencesCompat.apply(editor);
    }

读取SharedPreferences中数据

SharedPreferences 文件中读取数据会更加地简单。SharedPreferences对象中提供了一系列的get方法,用于对存储的数据进行读取,每种get方法都对应了SharedPreferences.Editor中的一种 put方法。

  /**
     * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
     *
     * @param context       上下文
     * @param key           key值
     * @param defaultObject 默认value值,当数据不存在或者类型不匹配时,尝试返回默认值或对应类型的值,都不是则返回null
     * @return value值
     */
    public static Object get(Context context, String key, Object defaultObject) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);

        if (defaultObject instanceof String) {
            return sp.getString(key, (String) defaultObject);
        } else if (defaultObject instanceof Integer) {
            return sp.getInt(key, (Integer) defaultObject);
        } else if (defaultObject instanceof Boolean) {
            return sp.getBoolean(key, (Boolean) defaultObject);
        } else if (defaultObject instanceof Float) {
            return sp.getFloat(key, (Float) defaultObject);
        } else if (defaultObject instanceof Long) {
            return sp.getLong(key, (Long) defaultObject);
        }

        return null;
    }

删除SharedPreferences中数据

  1. 删除某个特定的键值对,而不是清除整个SharedPreferences文件中的所有数据可以使用SharedPreferences.Editorremove(String key)方法。
  /**
     * 移除某个key值已经对应的值
     *
     * @param context 上下文
     * @param key     key值
     */
    public static void remove(Context context, String key) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.remove(key);
        SharedPreferencesCompat.apply(editor);
    }
  1. 删除或清除某个SharedPreferences文件中的所有数据,你不能直接删除文件本身(因为Android系统负责文件的管理),但你可以通过SharedPreferences.Editorclear()方法来清除所有存储的数据。
   /**
     * 清除所有数据
     *
     * @param context 上下文
     */
    public static void clear(Context context) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.clear();
        SharedPreferencesCompat.apply(editor);
    }

关于apply()commit() 方法

  • apply() 方法是异步的,它不会返回任何值,但会尽快将更改写入磁盘。
  • commit() 方法是同步的,它会返回一个布尔值来表示更改是否成功写入磁盘。然而,由于 apply() 方法提供了更好的性能,并且对于大多数用例来说,立即知道更改是否成功写入磁盘并不是必需的,因此 apply() 是更推荐的方法。

项目中使用 SharedPreferences例子

finnal
  1. 定义final关键字用于声明一个变量、方法或类不能被修改(对于变量)或不能被重写(对于方法和类)。

  2. 作用:

  • 对于变量:一旦给final变量赋了初值,这个值就不能被改变。这通常用于定义常量。

  • 对于方法final方法不能被子类重写。这通常用于防止方法被意外地修改其行为。

  • 对于类final类不能被继承。这通常用于设计那些你不希望被扩展的类,可能是出于安全考虑或设计上的决定。

  • 示例:在你的代码片段中,IF_FIRSTIS_ADMINACCOUNT都是使用final声明的字符串常量,这意味着这些字符串的值在编译时就已经确定,并且在整个程序中不能被改变。

static
  1. 定义static关键字用于声明属于类的变量和方法,而不是属于类的某个特定对象的实例变量和实例方法。

  2. 作用

  • 静态变量:属于类本身,在内存中只有一份拷贝,无论创建多少个对象,静态变量都只有一份拷贝被所有对象共享。
  • 静态方法:属于类的方法,可以在没有创建对象的情况下通过类名直接调用。静态方法内部只能访问类的静态变量和静态方法,不能直接访问类的实例变量和实例方法。
final和static结合使用
  • finalstatic一起使用时,它们通常用于定义类常量,这些常量在编译时就被确定,并且在整个类(甚至整个应用程序)中保持不变。
  • 示例中的IF_FIRSTIS_ADMINACCOUNTFILE_NAME都是类常量,它们在整个应用程序的生命周期内都是不变的。
创建一个存放SharedPreferences的工具类

主要包含了SharedPreferences的文件名,存储,读取,删除SharedPreferences数据等方法。具体代码:


/**
 * 数据持久化工具类
 */
public class SPUtils {
    public static final String IF_FIRST = "is_first";//是否第一次进来
    public static final String IS_ADMIN = "is_admin";//是否是管理员
    public static final String ACCOUNT = "account";//账号
    /**
     * 保存在手机里面的文件名
     */
    private static final String FILE_NAME = "share_data";
    /**
     * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
     *
     * @param context 上下文
     * @param key     key值
     * @param object  value值
     */
    public static void put(Context context, String key, Object object) {

        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();

        if (object instanceof String) {
            editor.putString(key, (String) object);
        } else if (object instanceof Integer) {
            editor.putInt(key, (Integer) object);
        } else if (object instanceof Boolean) {
            editor.putBoolean(key, (Boolean) object);
        } else if (object instanceof Float) {
            editor.putFloat(key, (Float) object);
        } else if (object instanceof Long) {
            editor.putLong(key, (Long) object);
        } else {
            editor.putString(key, object.toString());
        }

        SharedPreferencesCompat.apply(editor);
    }

    /**
     * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
     *
     * @param context       上下文
     * @param key           key值
     * @param defaultObject 默认value值,当数据不存在或者类型不匹配时,尝试返回默认值或对应类型的值,都不是则返回null
     * @return value值
     */
    public static Object get(Context context, String key, Object defaultObject) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);

        if (defaultObject instanceof String) {
            return sp.getString(key, (String) defaultObject);
        } else if (defaultObject instanceof Integer) {
            return sp.getInt(key, (Integer) defaultObject);
        } else if (defaultObject instanceof Boolean) {
            return sp.getBoolean(key, (Boolean) defaultObject);
        } else if (defaultObject instanceof Float) {
            return sp.getFloat(key, (Float) defaultObject);
        } else if (defaultObject instanceof Long) {
            return sp.getLong(key, (Long) defaultObject);
        }

        return null;
    }

    /**
     * 移除某个key值已经对应的值
     *
     * @param context 上下文
     * @param key     key值
     */
    public static void remove(Context context, String key) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.remove(key);
        SharedPreferencesCompat.apply(editor);
    }

    /**
     * 清除所有数据
     *
     * @param context 上下文
     */
    public static void clear(Context context) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        editor.clear();
        SharedPreferencesCompat.apply(editor);
    }

    /**
     * 查询某个key是否已经存在
     *
     * @param context 上下文
     * @param key     key值
     * @return 是否存在
     */
    public static boolean contains(Context context, String key) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        return sp.contains(key);
    }

    /**
     * 返回所有的键值对
     *
     * @param context 上下文
     * @return 所有的键值对
     */
    public static Map<String, ?> getAll(Context context) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        return sp.getAll();
    }

    /**
     * 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类
     *
     * @author zhy
     */
    private static class SharedPreferencesCompat {
        private static final Method sApplyMethod = findApplyMethod();

        /**
         * 反射查找apply的方法
         *
         * @return Method
         */
        @SuppressWarnings({"unchecked", "rawtypes"})
        private static Method findApplyMethod() {
            try {
                Class clz = SharedPreferences.Editor.class;
                return clz.getMethod("apply");
            } catch (NoSuchMethodException e) {
            }

            return null;
        }

        /**
         * 如果找到则使用apply执行,否则使用commit
         *
         * @param editor SharedPreferences.Edito
         */
        public static void apply(SharedPreferences.Editor editor) {
            try {
                if (sApplyMethod != null) {
                    sApplyMethod.invoke(editor);
                    return;
                }
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            editor.commit();
        }
    }

}
如何调用

在其余Activity或Fragment中调用get()方法获取当前账号及是否是管理员账号。

  private Boolean mIsAdmin;//是否管理员
  private String mAccount;//账号
 //在onCreate()方法中
 mIsAdmin = (Boolean) SPUtils.get(myActivity,SPUtils.IS_ADMIN,false);
 mAccount = (String) SPUtils.get(myActivity,SPUtils.ACCOUNT,"");

可通过三目运算符判断是否是管理员admin,设置视图的可见性。例如:

  • 三目运算符基本语法是条件 ? 表达式1 : 表达式2。如果条件为真(true),则整个表达式的结果是表达式1的结果;如果条件为假(false),则结果是表达式2的结果。
  • setVisibility(int visibility)方法用于设置视图的可见性。
  • View.VISIBLE作为参数时,视图可见。
  • View.GONE作为参数时,视图不可见且不占用布局空间。
 rbUserManage.setVisibility(mIsAdmin? View.VISIBLE: View.GONE);

SQLite数据库

在Android开发中,SQLite是一种常用的轻量级数据库,用于存储和管理应用程序的本地数据。

SQLite数据库的创建

需要创建一个继承自SQLiteOpenHelper的类,这个类将负责数据库的创建和版本管理。

  • 重写onCreate(SQLiteDatabase db)方法创建数据库。
  • 重写onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)方法数据库版本更新时调用
  • 其中 super(context, DATABASE_NAME, null, DATABASE_VERSION); 参数分别是上下文,数据库文件名称,结果集,版本号。
    class MyHelper extends SQLiteOpenHelper{
        //构造器,参数:上下文,数据库文件名称,结果集,版本号。定义数据库
        public MyHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
            super(context, name, factory, version);
        }
        //数据库初始化,创建表或视图文件
        @Override
        public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table user(user_id interger primary key ,userName varchar(10),password varchar(10))");
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        }
    }

SQLite数据库的增

使用MyHelper实例获取SQLiteDatabase对象,然后使用insert方法添加数据。

  1. getWritableDatabase()方法得到SOLiteDatabase 对象
  2. 获得ContentValues对象并将数据
    添加到ContentValues对象中
  3. 调用insert()方法将数据插入information表中。
  • insert()方法可以接收3个参数,第1个参数是数据表的名称;第2个参数表示,如果发现将要插人的行空行,会将这个列名的值设为null;第三个参数为ContentValues 对象。
  • ContentValues类类似于 Map类,通过键值对的形式存入数据,这里的 key 表示插入数据的列名,value表示要插入的数据
  • SQLiteDatabase 对象后一定要调用close()方法关闭数据库连接,否则数据库连接会一直存在,不断消耗内存
    //创建数据库和表
    public MyDbHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        db=this.getWritableDatabase();
    }
   //添加用户信息
    public boolean insertUser(String username,String password1,String password2){
        ContentValues contentValues=new ContentValues();
        contentValues.put("username",username);
        contentValues.put("password1",password1);
        contentValues.put("password2",password2);
        long i=db.insert("userInfo",null,contentValues);
        return i>0?true:false;
    }

SQLite数据库的删

使用SOLiteDatabase类中delete方法根据条件删除数据

  //删除数据,根据记录的用户名删除
    public boolean delatedUser(String deletedname){
        long i=db.delete("userInfo","username=?",new String[]{deletedname});
        return i>0?true:false;
    }

SQLite数据库的改

SQLiteDatabase 类中存在一个update()方法,用于修改数据库表中的数据。

  1. getWritableDatabase()方法得到SOLiteDatabase 对象db
  2. 获得ContentValues对象并将数据
    添加到ContentValues对象中
  3. 通过调用put()方法将需要修改的字段名称和字段值放人对象values中
  4. 通过对象db调用update()方法来修改数据库表中对应的数据。
  • update()方法传递了4个参数,其中,第1个参数表示数据库表的名称,第2个参数表示最新的数据,第3个参数表示要修改的数据的查找条件,第4个参数表示查找条件的参数
 //修改用户数据的更新
    public boolean updateUser(String username,String password1,String password2){
        ContentValues contentValues=new ContentValues();
        contentValues.put("username",username);
        contentValues.put("password1",password1);
        contentValues.put("password2",password2);
        long i=db.update("userInfo",contentValues,"username=?",new String[]{username});
        return i>0?true:false;
    }

SQLite数据库的查

在进行数据查询时使用的是query()方法,该方法返回的是一个行数集合Cursor。通过getCount()方法获取到查询结果的总数,然后通过moveToNext()方法移动游标指向下一行数据,接着通过为geiString()方法传入列名获取对应的数据。

  • Cursor是个游标接口,提供了遍历查询结果的方法。需要注意的是,在使用完Cursor后、一定要及时关闭,否则会造成内存泄露。
  • query()方法包含7个参数,第1个参数表示表名称,第2个参数表示查询的列,第3个参数表示的是接收查询条件的子句,第4个参数接收查询子句对应的条件值,第5个参数表示分组6个参数用于接收having条件(定义组的过滤器),第7个参数表示排序方式。
  //查询用户数据
    public userbean queryUser(String username){
        Cursor cursor=db.query("userInfo",null,"username=?",new String[]{username},null,null,null,null);
        if (cursor.getCount()==1){
            cursor.moveToFirst();
            String Id=cursor.getString(0);
            String Username=cursor.getString(1);
            String Password=cursor.getString(2);
            userbean ub=new userbean();
            ub.setId(Id);
            ub.setUsername(Username);
            ub.setPassword1(Password);
            cursor.close();
            return ub;
        }else {
            return null;
        }
    }

创建一个继承自SQLiteOpenHelper的类

将上方的几个方法汇总写入

public class MyDbHelper extends SQLiteOpenHelper {
    SQLiteDatabase db;
    //创建数据库和表
    public MyDbHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        db=this.getWritableDatabase();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table userInfo(id integer primary key autoincrement,username varchar(50),password1 varchar(10),password2 varchar(10))");}
     //添加用户信息
    public boolean insertUser(String username,String password1,String password2){
        ContentValues contentValues=new ContentValues();
        contentValues.put("username",username);
        contentValues.put("password1",password1);
        contentValues.put("password2",password2);
        long i=db.insert("userInfo",null,contentValues);
        return i>0?true:false;
    }
    //修改用户数据的更新
    public boolean updateUser(String username,String password1,String password2){
        ContentValues contentValues=new ContentValues();
        contentValues.put("username",username);
        contentValues.put("password1",password1);
        contentValues.put("password2",password2);
        long i=db.update("userInfo",contentValues,"username=?",new String[]{username});
        return i>0?true:false;
    }
    //删除数据,根据记录的用户名删除
    public boolean delatedUser(String deletedname){
        long i=db.delete("userInfo","username=?",new String[]{deletedname});
        return i>0?true:false;
    }
    //查询用户数据
    public userbean queryUser(String username){
        Cursor cursor=db.query("userInfo",null,"username=?",new String[]{username},null,null,null,null);
        if (cursor.getCount()==1){
            cursor.moveToFirst();
            String Id=cursor.getString(0);
            String Username=cursor.getString(1);
            String Password=cursor.getString(2);
            userbean ub=new userbean();
            ub.setId(Id);
            ub.setUsername(Username);
            ub.setPassword1(Password);
            cursor.close();
            return ub;
        }else {
            return null;
        }
    }
    //查询用户密码

    public userbean queryPassword(String username,String password1){
        Cursor cursor = db.query("userInfo", new String[]{"username", "password1"}, "password=1?", new String[]{username}, null, null, null, null);
        if (cursor.getCount()==1){
            cursor.moveToNext();
            int index1 = cursor.getColumnIndex("username");
            int index2 = cursor.getColumnIndex("password1");
            username = cursor.getString(index1);
            password1 = cursor.getString(index2);
            userbean ub=new userbean();
            ub.setUsername(username);
            ub.setPassword1(password1);
            cursor.close();
            return ub;
        }else {
            return null;
        }
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

如何调用

创建一个user实类
public class userbean {
    private String id;
    private String username;
    private String password1;
    private String password2;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword1() {
        return password1;
    }

    public void setPassword1(String password1) {
        this.password1 = password1;
    }

    public String getPassword2() {
        return password2;
    }

    public void setPassword2(String password2) {
        this.password2 = password2;
    }



}
数据添加
 //数据添加
 myDbHelper = new MyDbHelper(RegisterActivity.this, "db7.db", null, 1);
                         Boolean flag = myDbHelper.insertUser(ub.getUsername(), ub.getPassword1(), ub.getPassword2());

数据删除
 //获取编辑框中输入的内容
                String selection = e_selection.getText().toString();
                myDbHelper = new MyDbHelper(deteleActivity.this, "db10.db", null, 1);
                Boolean flag = myDbHelper.delatedData(selection);
                if (flag == true) {
                    //如果添加成功,将数据回传的结果设置为2
                    setResult(2);
                    Toast.makeText(deteleActivity.this, "删除成功!", Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(deteleActivity.this, "删除失败!", Toast.LENGTH_LONG).show();
                }
                break;
数据修改
                    //数据添加
                    myDbHelper=new MyDbHelper(modifyinfo.this,"db7.db",null,1);
                    Boolean flag=myDbHelper.updateUser(Name,Password1,Password2);
                    if (flag==true){
                        //如果添加成功,将数据回传的结果设置为2
                        // Intent intent1=new Intent();
                        //   intent1.putExtra("return","信息已成功收到");
                        setResult(2);
                        Toast.makeText(modifyinfo.this,"修改成功!",Toast.LENGTH_LONG).show();

                    }else{
                        Toast.makeText(modifyinfo.this,"修改失败!",Toast.LENGTH_LONG).show();
                    }
数据查询
   //判断用户是否存在
                     myDbHelper = new MyDbHelper(RegisterActivity.this, "db7.db", null, 1);
                     userbean findusername = myDbHelper.queryUser(getusername);
                     if (findusername == null) {
                         ub.setUsername(getusername);

Litepal

LitePal是一款开源的 Android数据库框架,它采用了对象关系映射(ORM)的模式,并将我们平时开发最常用到的一些数据库功能进行了封装,使得不用编写一行 SOL,语句就可以完成各种建表和增删改查的操作。

配置Litepal

  1. 编辑 app/build.gradle文件,在 dependencies 闭包中添加如下内容
 //litePal
    implementation 'org.litepal.android:core:1.6.1'
  1. 接下来需要配置 litepal.xml 文件。右击app/src/main 日录→New→Directory,创建一个 assets 目录,然后在assets目录下再新建一个litepal.xml文件,
<litepal>
    <!--数据库名称-->
    <dbname value="fruit"/>
    <!--数据库版本-->
    <version value="1"/>
    <list>
        <!--映射   每一张表 -->
        <mapping class="com.example.fruit.bean.User"/>
   </list>

</litepal>
  1. 配置一下 LitePalApplication,修改 AndroidManifest.xml中的代码
 android:name=".MyApplication"
  • MyApplication的作用:

    Android提供了一个Application类,每当应用程序启动的时候,系统就会自动将这个类进行初始化。而我们可以定制一个自己的 Application 类,以便于管理程序内一些全局的状态信息。

    经过这样的配置之后,LitePal就能在内部自动获取到Instance了并初始化了 LitePal 数据库

public class MyApplication extends Application {
    public static MyApplication Instance;
    @Override
    public void onCreate() {
        super.onCreate();
        Instance = this;
        //初始化LitePal数据库
        LitePal.initialize(this);

    }
    private Activity mMainActivity;

    public Activity getMainActivity() {
        return mMainActivity;
    }

    public  void setMainActivity(Activity mainActivity) {
        mMainActivity = mainActivity;
    }
}

如何调用

创建实体类:

通过注解定义数据库表结构,创建对应的实体类。


public class Goods extends DataSupport implements Serializable {
    private Integer typeId;//类型
    private String title;//标题
    private String img;//图片
    private String content;//内容
    private String price;//价格
    private String date;//时间

    public Integer getTypeId() {
        return typeId;
    }

    public void setTypeId(Integer typeId) {
        this.typeId = typeId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getImg() {
        return img;
    }

    public void setImg(String img) {
        this.img = img;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public Goods(Integer typeId, String title, String img, String content, String price, String date) {
        this.typeId = typeId;
        this.title = title;
        this.img = img;
        this.content = content;
        this.price = price;
        this.date = date;
    }
}

添加修改数据

判断数据库中是否存在了该商品,存在不保存,不存在则添加商品,或重新设定。

 public void save1(View view) {
        String title=etTitle.getText().toString();
        String price=etprice.getText().toString();
        String img=etImg.getText().toString();
        String content=etContent.getText().toString();
        Integer typeId=spType.getSelectedItemPosition();
        if ("".equals(title)) {
            Toast.makeText(myActivity,"标题不能为空", Toast.LENGTH_LONG).show();
            return;
        }
        if ("".equals(price)) {
            Toast.makeText(myActivity,"价格不能为空", Toast.LENGTH_LONG).show();
            return;
        }
        if ("".equals(img)) {
            Toast.makeText(myActivity,"图片地址不能为空", Toast.LENGTH_LONG).show();
            return;
        }
        if ("".equals(content)) {
            Toast.makeText(myActivity,"描述不能为空", Toast.LENGTH_LONG).show();
            return;
        }
        Goods goods=null;
        //如果 title与 mfruit 的标题不同,或者 mfruit 为 nu11,
        // 这段代码将执行査询并返回第一个找到的 Fruit 对象给 fruit 变量。
        // 如果查询结果为空,fruit 仍然保持为 nu11 。
        if(!title.equals(mgoods!=null?mgoods.getTitle():"")) {
            goods = DataSupport.where("title=?", title).findFirst(Goods.class);
        }
            if (goods == null) {
                if (mgoods != null) {
                    goods = DataSupport.where("title=?", mgoods.getTitle()).findFirst(Goods.class);
                    goods.setTypeId(typeId);
                    goods.setTitle(title);
                    goods.setPrice(price);
                    goods.setImg(img);
                    goods.setContent(content);
                } else {
                    goods = new Goods(typeId, title, img, content, price, sf.format(new Date()));
                }
                goods.save();
                setResult(RESULT_OK);
                finish();
                Toast.makeText(myActivity, "保存成功", Toast.LENGTH_LONG).show();
            } else {
                Toast.makeText(myActivity, "该标题已存在", Toast.LENGTH_LONG).show();
            }
        }

}
删除数据
 private List<Goods> list =new ArrayList<>();
  Goods goods=list.get(i);
  .....
    public void onClick(DialogInterface dialog, int which) {
                                list.remove(goods);
                                goods.delete();
                                notifyDataSetChanged();
                                Toast.makeText(mActivity,"删除成功", Toast.LENGTH_LONG).show();}
查找数据
  Goods mgoods=(Goods) getIntent().getSerializableExtra("goods");
            tvTitle.setText(mgoods.getTitle());
            tvPrice.setText(mgoods.getPrice());
            tvContent.setText(mgoods.getContent());
            tvDate.setText(String.format("上架时间:%s",mgoods.getDate()));
            Glide.with(mActivity)
                    .asBitmap()
                    .load(mgoods.getImg())
                    .error(R.drawable.ic_error)
                    .skipMemoryCache(true)
                    .diskCacheStrategy(DiskCacheStrategy.NONE)
                    .into(ivImg);

序列化

序列化是一个重要的概念,它涉及到将对象的状态信息转换为可以存储或传输的形式(如保存到文件、通过网络发送等),以及之后能够将这些信息恢复回原来的对象。

什么是序列化和反序列化

  • 序列化:将java堆内存中的对象转为二进制字节码;

  • 反序列化:将二进制字节码转为java对象

为什么要序列化(序列化转成二进制码的目的)?

一句话解释:可传输、可存储、持久化。

将内存中的对象的状态信息转换为可以存储或者传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或者持久性存储区。以后,可以从存储区中读取或者反序列化对象的状态,重新创建该对象。简单地说,序列化就是讲运行时的对象状态转换成为二进制,然后保存到流、内存或者通过网络传输给其他端.

序列化(Serialization)

序列化是指将数据结构或对象状态转换为可以存储或传输的格式的过程。这种格式通常是平台无关的,可以是二进制流、文本文件(如XML、JSON)等。序列化的目的是将对象的状态保存下来,以便可以在程序的后续运行中重新加载,或者通过网络传输到另一个系统或应用程序中。

序列化通常涉及以下几个步骤:

  1. 遍历对象:访问对象的所有成员变量。
  2. 转换成员变量:将成员变量的值转换为可以存储或传输的格式。
  3. 写入:将转换后的数据写入到存储介质(如文件、数据库)或通过网络发送到其他系统。

反序列化(Deserialization)

反序列化是序列化的逆过程,即将存储或传输的格式转换回原始的数据结构或对象的过程。反序列化的目的是重新构造对象,使其具有序列化时的状态。

反序列化通常涉及以下几个步骤:

  1. 读取:从存储介质(如文件、数据库)或网络接收序列化后的数据。
  2. 解析:解析接收到的数据,提取出对象的成员变量值。
  3. 重构对象:使用提取出的成员变量值,重新构造出原始的对象。

serialVersionUID

序列化操作的时候系统会把当前类的serialVersionUID写入到序列化文件中,当反序列化时系统会去检测文件中的serialVersionUID,判断它是否与当前类的serialVersionUID一致,如果一致就说明序列化类的版本与当前类版本是一样的,可以反序列化成功,否则失败。

Android,有多种方式可以存储数据,以下是其一些常见的数据存储方式: 1. Shared Preferences(共享首选项): - Shared Preferences是Android提供的一种轻量级的存储方式,用于存储少量的键值对数据。它适用于存储一些简单的配置信息或用户偏好设置。Shared Preferences使用键值对的方式存储数据,并且只能存储基本数据类型。 2. 内部存储: - 内部存储是应用程序私有的文件存储空间,可以用来存储应用程序的私有数据。可以使用File类来进行读写操作。内部存储适用于存储较小的数据文件。 3. 外部存储: - 外部存储是指SD卡或其他外部存储设备上的存储空间。Android提供了一些API(如Environment.getExternalStorageDirectory())来访问外部存储。外部存储适用于存储大量的文件或多媒体资源。 4. SQLite数据库: - SQLite是Android内置的关系型数据库,可以用于存储结构化的数据。开发者可以使用SQLiteOpenHelper类来创建和管理数据库,以及执行常见的CRUD(创建、读取、更新、删除)操作。 5. ContentProvider(内容提供器): - ContentProvider是用于在应用程序之间共享数据的组件。它提供了标准的接口和方法,允许应用程序对数据进行查询、插入、更新和删除操作。ContentProvider常用于共享数据库或文件等数据。 6. 网络存储: - Android应用程序可以通过网络与服务器进行数据交互,将数据存储在远程服务器上。常用的网络存储方式包括使用HTTP协议与服务器进行通信、使用RESTful API进行数据交互等。 综上所述,Android有多种数据存储方式可供选择,开发者可以根据具体的需求和场景选择合适的方式来存储和管理数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值