Android local data storage (SP, SQLite, Room)

There are three commonly used methods for Android local data storage

1. SP storage, key-value storage in the local xml file, /data/data/xxx.xx/shared_prefs/xxx.xml
2. sqlite storage
3. room storage

1. SP storage usage

SP is usually used to store configuration information, if a small amount of data such as app style theme, login user name, password, etc., it is not suitable for storing large amounts of data.

Get the operation instance object by calling the base class method getSharedPreferences() in the Activity

This method needs to pass in two parameters

  • Parameter 1, the name of the xml file that stores the data
  • Parameter 2, mode, has 3 optional values, and uses Context.MODE_PRIVATE by default
  1. MODE_PRIVATE: Only this application can read and write this file
  2. MODE_WORLD_READABLE: Other applications can only read and not modify this SharedPreferences file.
  3. MODE_WORLD_WRITEABLE: This SharedPreferences file can be read and written by other applications.

Use the code example

1. When the login is successful, store the account password

// 登录成功记录本次登录信息
SharedPreferences sp = getSharedPreferences("login_sp_info", Context.MODE_PRIVATE);
SharedPreferences.Editor edit = sp.edit();
edit.putString("username",usernameEditText.getText().toString());
edit.putString("password",passwordEditText.getText().toString());
edit.apply();//提交数据保存

2. When the app is opened, the stored account password is obtained and displayed on the page

//设置上次记录的用户信息
SharedPreferences sp = getSharedPreferences("login_sp_info", Context.MODE_PRIVATE);
String username = sp.getString("username","");
String password = sp.getString("password","");
companycodeEditText.setText(companycode);
usernameEditText.setText(username);
passwordEditText.setText(password);

Two, SQLite storage use

  • SQLite is a lightweight database designed to be embedded with very low resource usage
  • SQLite has no server process and saves data through files, which are cross-platform
  • Supports five data types: null, integer, real, text, and blob. In fact, SQLite also accepts data types such as varchar, char, and decimal, but it will be converted into the corresponding five data types during operation or storage. Therefore, you can Save various types of data into any field

1. Create a database

The Android system recommends using a subclass of SQLiteOpenHelper to create a database, so you need to create a class that inherits from SQLiteOpenHelper and rewrite the onCreate and onUpgrade methods of this class.

Here, the singleton mode is used to create, and the database creation operation will be automatically performed when DBHelper is called for the first time

public class DBHelper extends SQLiteOpenHelper {
    
    

    private volatile static DBHelper instance;

    public static DBHelper getInstance(Context context) {
    
    
        if (instance == null) {
    
    
            synchronized (DBHelper.class) {
    
    
                if (instance == null) {
    
    
                    instance = new DBHelper(context, "mytest.db", null, 1);
                }
            }
        }
        return instance;
    }

    /**
     * 作为SQLiteOpenHelper子类必须有的构造方法
     * @param context 上下文参数
     * @param name 数据库名字
     * @param factory 游标工厂 ,通常是null
     * @param version 数据库的版本
     */
    private DBHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
    
    
        super(context, name, factory, version);
    }

    /**
     * 数据库第一次被创建时调用该方法
     * @param db
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
    
    
        // 初始化数据库的表结构,执行一条建表的SQL语句
        String sql ="create table persons(_id integer primary key autoincrement, name text, sex text, age integer)";
        db.execSQL(sql);
    }

    /**
     * 当数据库的版本号增加调用
     * @param db
     * @param oldVersion
     * @param newVersion
     */
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    
    

    }
}

2. Add, delete, modify and check operations

SQLiteOpenHelper provides a method to directly execute sql statements execSQL(), and also provides four methods for adding, deleting, modifying and checkinginsert、delete、update、query

1) Insert data

Method 1, execute sql

public void insert(View view) {
    
    
    DBHelper instance = DBHelper.getInstance(this);
    SQLiteDatabase db = instance.getWritableDatabase();
    if (!db.isOpen()) {
    
    
        return;
    }
    String sql = "insert into persons(name,sex,age) values('张三','男',20)";
    db.execSQL(sql);
    db.close();
}

Method 2, execute the insert method

public void insert2(View view) {
    
    
    DBHelper instance = DBHelper.getInstance(this);
    SQLiteDatabase db = instance.getWritableDatabase();
    if (!db.isOpen()) {
    
    
        return;
    }

    ContentValues values = new ContentValues();
    values.put("name", "王五");
    values.put("sex", "女");
    values.put("age", 30);
    // 插入数据
    // insert方法参数1:要插入的表名
    // insert方法参数2:如果发现将要插入的行为空时,会将这个列名的值设为null
    // insert方法参数3:contentValue
    db.insert("persons", null, values);
    db.close();
}

2) Delete data

public void deleteData(View view) {
    
    
    DBHelper instance = DBHelper.getInstance(this);
    SQLiteDatabase db = instance.getWritableDatabase();
    if (!db.isOpen()) {
    
    
        return;
    }
    String sql = "delete from persons where _id=?";
    db.execSQL(sql, new Object[]{
    
    3});
    db.close();
}

3) Modify data

public void updateData(View view) {
    
    

    DBHelper instance = DBHelper.getInstance(this);
    SQLiteDatabase db = instance.getWritableDatabase();
    if (!db.isOpen()) {
    
    
        return;
    }
    String sql = "update persons set name =? where _id=?";
    db.execSQL(sql, new Object[]{
    
    "李四", 2});
    db.close();
}

4) Query data

Method 1, execute sql

public void query(View view) {
    
    
    DBHelper instance = DBHelper.getInstance(this);
    SQLiteDatabase db = instance.getReadableDatabase();
    if (!db.isOpen()) {
    
    
        return;
    }
    Cursor cursor = db.rawQuery("select * from persons", null);
    while (cursor.moveToNext()) {
    
    
        int _id = cursor.getInt(cursor.getColumnIndex("_id"));
        String name = cursor.getString(cursor.getColumnIndex("name"));
        String sex = cursor.getString(cursor.getColumnIndex("sex"));
        int age = cursor.getInt(cursor.getColumnIndex("age"));
        Log.d("test", "query: _id: " + _id + ", name: " + name + ",sex: " + sex + ",age: " + age);
    }
    cursor.close();
    db.close();
}

Method 2, execute the query method

public void query2(View view) {
    
    
    DBHelper instance = DBHelper.getInstance(this);
    SQLiteDatabase db = instance.getReadableDatabase();
    // 参数1:table_name
    // 参数2:columns 要查询出来的列名。相当于 select  *** from table语句中的 ***部分
    // 参数3:selection 查询条件字句,在条件子句允许使用占位符“?”表示条件值
    // 参数4:selectionArgs :对应于 selection参数 占位符的值
    // 参数5:groupby 相当于 select *** from table where && group by ... 语句中 ... 的部分
    // 参数6:having 相当于 select *** from table where && group by ...having %%% 语句中 %%% 的部分
    // 参数7:orderBy :相当于 select  ***from ??  where&& group by ...having %%% order by@@语句中的@@ 部分,如: personid desc(按person 降序)
    Cursor cursor = db.query("persons", null, null, null, null, null, null);
    while (cursor.moveToNext()) {
    
     // 游标只要不是在最后一行之后,就一直循环
        int _id = cursor.getInt(0);
        String name = cursor.getString(1);
        String sex = cursor.getString(2);
        int age = cursor.getInt(3);
        Log.d("test", "query: _id: " + _id + ", name: " + name + ",sex: " + sex + ",age: " + age);
    }
    cursor.close();
    db.close();
}

3. Use of Room storage

Room has an ORM package based on SQLite, which is similar to JPA in use and does not need to write too much sql.

Prepare, import dependencies

//room
def room_version="2.4.2"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
//implementation "androidx.room:room-rxjava2:$room_version"
//implementation "androidx.room:room-rxjava3:$room_version"
//implementation "androidx.room:room-guava:$room_version"
//testImplementation "androidx.room:room-testing:$room_version"
//implementation "androidx.room:room-paging:2.5.0-alpha01"

Key Notes

1. @Database: Room database object. This class needs to inherit from RoomDatabase, and complete the creation of the database through Room.databaseBuilder() combined with the singleton design pattern. The Dao object we created is returned here in the form of an abstract method, and only one line of code is required.

  • entities: specify which tables the database has
  • version: Specifies the database version number, and subsequent database upgrades are judged based on the version number

2. @Entity: This class is associated with the table in Room. The tableName attribute can set the name for the table, if not set, the table name is the same as the class name.

3. @PrimaryKey: Used to specify the field as the primary key of the table.

4. @ColumnInfo: Set the name of the field stored in the database table and specify the type of the field; the default field name is the same as the attribute name

5. @Ignore: Ignore this field

Use the code example

1. Create an entity class, corresponding to a table in the database, using the annotation @Entity

@Entity
public class Person {
    
    

    // 主键,自增长
    @PrimaryKey(autoGenerate = true)
    private int id;
    private String name;
    private String sex;
    private int age;
}

2. Create a Dao class for manipulating data and use the annotation @Dao

@Dao
public interface PersonDao {
    
    
    // 插入
    @Insert
    void insertPersons(Person... persons);
    // 修改
    @Update
    void updatePersons(Person... persons);
    // 删除所有
    @Query("delete from Person")
    void deleteAllPersons();
    // 删除指定实体
    @Delete
    void deletePersons(Person... persons);
    // 根据id删除
    @Query("delete from Person where id in (:ids)")
    void deleteByIds(int ...ids);
    // 根据id查询
    @Query("select * from Person where id in (:ids)")
    List<Person> selectByIds(int ...ids);
    // 查询所有
    @Query("select * from Person order by id desc")
    List<Person> selectAllPersons();
}

3. Create a database object Database, inherit RoomDatabase, and use the singleton mode to return an instance

@Database(entities = {
    
    Person.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    
    
    public abstract PersonDao personDao();

    private volatile static AppDatabase instance;

    public static AppDatabase getInstance(Context context){
    
    
        if (instance == null) {
    
    
            synchronized (DBHelper.class) {
    
    
                if (instance == null) {
    
    
                    instance = Room.databaseBuilder(context, AppDatabase.class, "person.db").build();
                }
            }
        }
        return instance;
    }
}

4. Use in Activity

Room data operations must be performed in an asynchronous thread, so use the thread pool to perform in the Activity

ExecutorService pool = Executors.newCachedThreadPool();

// 插入数据
public void insertRoom(View view) {
    
    
    AppDatabase db = AppDatabase.getInstance(getApplicationContext());

    pool.execute(() -> {
    
    
        PersonDao dao = db.personDao();
        Person p1 = new Person("用户1", "男", 18);
        Person p2 = new Person("用户2", "男", 28);
        Person p3 = new Person("用户3", "男", 38);
        dao.insertPersons(p1, p2, p3);
    });

}

// 查询数据
public void queryRoom(View view) {
    
    

    AppDatabase db = AppDatabase.getInstance(getApplicationContext());

    pool.execute(() -> {
    
    

        PersonDao dao = db.personDao();
        List<Person> list = dao.selectAllPersons();
        list.forEach(p-> Log.d("test", p.toString()));

    });
}

// 根据id查询
public void queryRoomById(View view) {
    
    

    AppDatabase db = AppDatabase.getInstance(getApplicationContext());

    pool.execute(() -> {
    
    

        PersonDao dao = db.personDao();
        List<Person> list = dao.selectByIds(3,4);
        list.forEach(p-> Log.d("test", p.toString()));

    });
}

// 删除
public void deleteRoom(View view) {
    
    

    AppDatabase db = AppDatabase.getInstance(getApplicationContext());

    pool.execute(() -> {
    
    

        PersonDao dao = db.personDao();
        dao.deleteByIds(1,2);
    });
}

Guess you like

Origin blog.csdn.net/wlddhj/article/details/127820069