frameworks\base\core\java\android\database\sqlite\SQLiteOpenHelper.java
数据库的创建与版本更新管理辅助类,这个辅助类使得对ContentProvider控制更容易,这个辅助类创建的时候并不会创建数据库或者升级数据库,而只有在使用数据库的时候才会第一次创建数据库或者升级数据库,从而延迟数据库创建与升级,避免在应用启动的时候阻塞应用,而直接使用contentprovider 就会导致创建、升级数据库应用启动慢。
public abstract class SQLiteOpenHelper {
private SQLiteDatabase mDatabase; //
}
nchronized void | close() Close any open database object. |
synchronizedSQLiteDatabase | getReadableDatabase() Create and/or open a database. |
synchronizedSQLiteDatabase | getWritableDatabase() Create and/or open a database that will be used for reading and writing. |
abstract void | onCreate(SQLiteDatabase db)(在派生类中必须被重写) Called when the database is created for the first time. |
void | onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) Called when the database needs to be downgraded. |
void | onOpen(SQLiteDatabase db) Called when the database has been opened. |
abstract void | onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)(在派生类中必须被重写) Called when the database needs to be upgraded. |
它提供了两个重要的方法,分别是
onCreate(SQLiteDatabase db):用户初次使用软件时生成数据库,一旦数据库存在则不会调用此方法。函数是在第一次创建数据库的时候执行的,仅仅生成DataBaseHelper对象(SQLiteOpenHelper类型)的时候是不会调用该函数的,而只有当调用DataBaseHelper对象的getReadableDataBase时或者是调用了getWritableDataBase时,如果是第一次创建数据库,那么就一定会调用onCreate()函数。
onUpgrade(SQLiteDatabase db,int oldVersion,int vewVersion):用于升级软件时更新数据库表结构,如增加表、列字段等操作。
提示一下,在软件升级前,最好对原有数据进行备份,在新表建好后把数据导入新表中。
实现了这两个方法,就可以用它的getWritableDatabase()和getReadableDatabase()来获得数据库(SQLiteDatabase 对象)。
强调下:当第一次创建数据库时,当实现DataBaseHelper对象的getReadableDataBase时或者是调用了getWritableDataBase时,系统自动调用oncreater()方法(当然程序中也可以调用);
如果用户需要升级数据库表结构,需要主动调用onUpgrade(SQLiteDatabase db,int oldVersion,int vewVersion),传入一个新的版本的号。
继承该类并覆盖onCreate,onUpgrade,onOpen(可选)。我们可以创建或打开数据库,并对其进行升级。通过getReadableDataBase和getWritableDataBase获取SQliteDataBase实例。通过close关闭数据库。
Sdk\sources\android-28\android\content\ContentProvider.java
public abstract boolean onCreate();
这里在应用启动时会在主线程中调用,创建数据库。
在使用时,可以在onCreate()中初始化 DatabaseHelper,在应用中通过
getContentResolver().query 。。。。 调用MyContentProvider 中方法,从而达到不让应用阻塞
@Override public boolean onCreate() { mDatabaseHelper = new MyDatabaseHelper(getContext()); return true; }
MainActivity.java
package com.wuyue.testcontentprovider; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.Toast; import java.util.Random; public class MainActivity extends Activity { static final String TAG = "CONTENTPROVIDER"; ContentResolver mContentResolver; Uri mUri = Uri.parse("content://org.wuyue.statistic.list/"); MyContentProvider mContentProvider; SQLiteDatabase mSQLdb; String mDbFilePath; static final String TABLE_NAME = "new_infs"; static final String TABLE_CREATE = "create table " + TABLE_NAME + "(_id integer" + " primary key autoincrement," + " news_title varchar(50)," + " news_content varchar(255))"; Button mButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //create db // mDbFilePath = this.getFilesDir().toString() + "/wuyue.db"; // Log.d(TAG,"database path:" + mDbFilePath); // mSQLdb = SQLiteDatabase.openOrCreateDatabase(mDbFilePath,null); // try { // mSQLdb.execSQL(TABLE_CREATE); // }catch (SQLException e){ // Log.d(TAG,"" + e); // } //mContentProvider = new MyContentProvider(); mButton = (Button)findViewById(R.id.btn); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Random random = new Random(); int r = random.nextInt(); ContentValues values = new ContentValues(); values.put("news_title","abc" + r); values.put("news_content","abc"); //mSQLdb.insert(TABLE_NAME,null,values); Uri uri = Uri.parse("content://org.wuyue.statistic.list/" + TABLE_NAME); //mContentProvider.insert(uri,values); getContentResolver().insert(uri,values); String[] cols = {"_id","news_title","news_content"}; // Cursor c = mSQLdb.query(TABLE_NAME,cols,null,null,null,null,null); //Cursor c = mContentProvider.query(uri,null,null,null,null,null); Cursor c = getContentResolver().query(uri,null,null,null,null); if(c.getCount() > 0){ while(c.moveToNext()){ String id = c.getString(0); String title = c.getString(1); String content = c.getString(2); Log.d(TAG,"id = " + id + " title= " + title + " content= " + content); } } } }); mContentResolver = getContentResolver(); } @Override protected void onDestroy() { super.onDestroy(); if(mSQLdb != null && mSQLdb.isOpen()){ mSQLdb.close(); } } public void insert(View source){ ContentValues cv = new ContentValues(); cv.put("name","abc"); Uri newUri = mContentResolver.insert(mUri,cv); Toast.makeText(this,"insert" + newUri,Toast.LENGTH_LONG).show(); } public void query(View source){ Cursor c = mContentResolver.query(mUri,null,"query_where",null,null); Toast.makeText(this,"query" + c ,Toast.LENGTH_LONG).show(); } }
MyContentProvider.java
package com.wuyue.testcontentprovider; import android.content.ContentProvider; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.os.Bundle; import android.os.CancellationSignal; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import java.util.Random; public class MyContentProvider extends ContentProvider{ private final static int NEW_INFS = 0, BOOK = 1; private final static String authority = "org.wuyue.statistic.list"; private static UriMatcher mMatcher = new UriMatcher(UriMatcher.NO_MATCH); private MyDatabaseHelper mDatabaseHelper; static { mMatcher.addURI(authority, "new_infs", NEW_INFS);//TABLE new_infs mMatcher.addURI(authority, "book", BOOK); } public MyContentProvider() { super(); } private String getTableName(Uri uri) { int code = mMatcher.match(uri); switch (code) { case NEW_INFS: return "new_infs"; case BOOK: return "book"; default: return null; } } @Override public boolean onCreate() { mDatabaseHelper = new MyDatabaseHelper(getContext()); return true; } @Nullable @Override public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { String table = getTableName(uri); if (table != null) { mDatabaseHelper.insert(table/*mDatabaseHelper.getDatabaseName()*/,null,values); return uri; } return null; } @Override public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; } @Override public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; } @Nullable @Override public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal) { String table = getTableName(uri); if (table != null) { String[] cols = {"_id", "news_title", "news_content"}; return mDatabaseHelper.query(/*mDatabaseHelper.getDatabaseName()*/table,cols,null,null,null,null,null); } return super.query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal); } @Nullable @Override public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal) { return super.query(uri, projection, queryArgs, cancellationSignal); } @Nullable @Override public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { return null; } @Nullable @Override public String getType(@NonNull Uri uri) { return null; } }
MyDatabaseHelper.java
package com.wuyue.testcontentprovider; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import java.util.Random; public class MyDatabaseHelper extends SQLiteOpenHelper{ static final String TABLE_NAME = "new_infs"; static final String TABLE_CREATE = "create table " + TABLE_NAME + "(_id integer" + " primary key autoincrement," + " news_title varchar(50)," + " news_content varchar(255))"; public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context.getApplicationContext(), name, factory, version); } public MyDatabaseHelper(Context context){ super(context.getApplicationContext(), TABLE_NAME, null, 1); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(TABLE_CREATE); } @Override public void onOpen(SQLiteDatabase db) { super.onOpen(db); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if(newVersion > oldVersion){ db.execSQL("delete from " + TABLE_NAME); } } @Override public SQLiteDatabase getWritableDatabase() { return super.getWritableDatabase(); } @Override public SQLiteDatabase getReadableDatabase() { return super.getReadableDatabase(); } public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy){ Cursor c = getReadableDatabase().query(table, columns, selection,selectionArgs,groupBy,having,orderBy); return c; } public long insert(String table, String nullColumnHack, ContentValues values){ return getWritableDatabase().insert(table,nullColumnHack,values); } }
AndroidManifest.xml