Technology Sharing

Android Database Basics

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Table of contents

1. Android data storage method

2. Database Transactions

Characteristics of database transactions (ACID)

Transaction isolation level

Transaction Summary

3、ContetProvider

effect

​Edit

Uniform Resource Identifier (URI)

​Edit

MIME Type

ContentProvider Main Methods

4、ContentResolver

effect

Main methods

Use Cases

Auxiliary tools

ContentUris

UriMatcher

ContentObserver


1. Android data storage method

  • SharedPreference
  • File Storage
  • SQLite
  • Network Storage

2. Database Transactions

Characteristics of database transactions (ACID)

  • Atomicity: All operations in a transaction must either succeed or be rolled back to their original state.
  • Consistency: The state of the database remains consistent before and after the transaction is executed
  • Isolation: Multiple users access the database concurrently, and multiple transactions do not affect each other
  • Persistence: Once a transaction is committed, the database data is permanently modified.

Transaction isolation level

  • Read Uncommitted
  • Read Committed: Avoid Dirty Reads (Reading Uncommitted Data)
  • Repeatability: Avoid non-repeatable reads (for the current transaction, even if the source data is modified by another transaction, the data it sees is still the state at the start of the transaction)
  • Serialization: Avoid phantom reads (after a transaction has started and read data, another transaction inserts new records, so that the first transaction may see new data that was not read before in subsequent operations.)

Transaction Summary

3、ContetProvider

effect

  • The underlying principle is to use the Binder mechanism
  • Provide a unified interface for storing and retrieving data, and realize data sharing between applications
  • Data in different ContentProviders can be operated through URI
  • External processes can interact with ContentProvider through the ContentResolver class

  • Inter-process data interaction and sharing to achieve cross-process communication
  • ContentProvider is equivalent to a porter. The real data source is still the database, file, XML, network

Uniform Resource Identifier (URI)

Uniquely identifies the data in ContentProvider

MIME Type

Specify a certain extension file to open with a certain application

MIME type composition = type + subtype

like:

  • text/html
  • text/xml
  • text/css
  • application/pdf

MIME type format

ContentProvider Main Methods

//外部进程向ContentProvider中添加数据
fun insert(uri:Uri,contentValues values):Uri
//外部进程删除ContentProvider中数据
fun delete(uri:Uri,selection:String,selectionArgs:String[]):Int
//外部进程更新ContentProvider中数据
fun update(uri:Uri,values:ContentValues,selection:String,selectionArgs:String[]):int
//外部应用获取ContentProvider中数据
fun query (uri:Uri,projection:String[],selection:String,selectionArgs:String[],sortOrder:String):Cursor

4、ContentResolver

effect

You can operate data in different ContentProviders through URI

External processes interact with ContentProvider through ContentResolver

Unified management of all ContentProviders

Main methods

ContentResolverThe class providesContentProvider4 methods with the same class name & function

//外部进程向ContentProvider中添加数据
fun insert(uri:Uri,contentValues values):Uri
//外部进程删除ContentProvider中数据
fun delete(uri:Uri,selection:String,selectionArgs:String[]):Int
//外部进程更新ContentProvider中数据
fun update(uri:Uri,values:ContentValues,selection:String,selectionArgs:String[]):int
//外部应用获取ContentProvider中数据
fun query (uri:Uri,projection:String[],selection:String,selectionArgs:String[],sortOrder:String):Cursor

Use Cases

val resolver = getContentResolver()
val uri = Uri.parse("content://cn.scu.myprovider/user")

val cursor:Cursor = resolver.query(uri,null,null,null,"userid desc")

Auxiliary tools

ContentUris

Append to URI & get ID

// withAppendedId()作用:向URI追加一个id
Uri uri = Uri.parse("content://cn.scu.myprovider/user") 
Uri resultUri = ContentUris.withAppendedId(uri, 7);  
// 最终生成后的Uri为:content://cn.scu.myprovider/user/7

// parseId()作用:从URL中获取ID
Uri uri = Uri.parse("content://cn.scu.myprovider/user/7") 
long personid = ContentUris.parseId(uri); 
//获取的结果为:7

UriMatcher

Register the URI in the ContentProvider, return the registration code based on the URI, and match the corresponding data table in the ContentProvider

// 步骤1:初始化UriMatcher对象
    UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); 
    //常量UriMatcher.NO_MATCH  = 不匹配任何路径的返回码
    // 即初始化时不匹配任何东西

// 步骤2:在ContentProvider 中注册URI(addURI())
    int URI_CODE_a = 1;
    int URI_CODE_b = 2;
    matcher.addURI("cn.scu.myprovider", "user1", URI_CODE_a); 
    matcher.addURI("cn.scu.myprovider", "user2", URI_CODE_b); 
    // 若URI资源路径 = content://cn.scu.myprovider/user1 ,则返回注册码URI_CODE_a
    // 若URI资源路径 = content://cn.scu.myprovider/user2 ,则返回注册码URI_CODE_b

// 步骤3:根据URI 匹配 URI_CODE,从而匹配ContentProvider中相应的资源(match())

@Override   
    public String getType(Uri uri) {   
      Uri uri = Uri.parse(" content://cn.scu.myprovider/user1");   

      switch(matcher.match(uri)){   
     // 根据URI匹配的返回码是URI_CODE_a
     // 即matcher.match(uri) == URI_CODE_a
      case URI_CODE_a:   
        return tableNameUser1;   
        // 如果根据URI匹配的返回码是URI_CODE_a,则返回ContentProvider中的名为tableNameUser1的表
      case URI_CODE_b:   
        return tableNameUser2;
        // 如果根据URI匹配的返回码是URI_CODE_b,则返回ContentProvider中的名为tableNameUser2的表
    }   
}

ContentObserver

Observe the URI causing data changes in ContentProvider & notify visitors

// 步骤1:注册内容观察者ContentObserver
    getContentResolver().registerContentObserver(uri);
    // 通过ContentResolver类进行注册,并指定需要观察的URI

// 步骤2:当该URI的ContentProvider数据发生变化时,通知外界(即访问该ContentProvider数据的访问者)
    public class UserContentProvider extends ContentProvider { 
      public Uri insert(Uri uri, ContentValues values) { 
      db.insert("user", "userid", values); 
      getContext().getContentResolver().notifyChange(uri, null); 
      // 通知访问者
   } 
}

// 步骤3:解除观察者
 getContentResolver().unregisterContentObserver(uri);
    // 同样需要通过ContentResolver类进行解除