四大組件初始之ContentProvider
在android中,除了存放在外部存儲的共享目錄下的數據,各個應用的數據庫文件,資源等都是私有的,其他應用沒有訪問權限。所以有了ContentProvider,不包含功能邏輯,用於不同應用進程間共享數據,是數據訪問的接口。
一、工作流程
為了快速熟悉ContentProvider的工作流程。先創建一個沒有具體實現的ContentProvider。
1、創建ContentProvider
只要繼承android提供的ContentProvider並實現抽象方法即可。
import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Process; import android.util.Log; public class MyContentProvider extends ContentProvider { private final static String Tag="ContentProvider"; public MyContentProvider() { } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { Log.d(Tag,"................delete"); return 0; } @Override public String getType(Uri uri) { return null; } @Override public Uri insert(Uri uri, ContentValues values) { Log.d(Tag,".................insert"); return null; } @Override public boolean onCreate() { Log.d(Tag,"..................onCreate,PID="+ Process.myPid()); return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Log.d(Tag,".................query"); return null; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { Log.d(Tag,"...................update"); return 0; } }
2、註冊
應用的組件都要在清單文件裏面註冊。
為了說明ContentProvider工作在不同的進程間,使用process屬性。
3、訪問
使用URI定位一個ContentProvide,URI值為註冊時的authorities屬性。
import android.content.ContentResolver; import android.net.Uri; import android.os.Process; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; public class MainActivity extends AppCompatActivity { private final static String Tag="MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d(Tag,"..............onCreate PID="+ Process.myPid()); Uri uri=Uri.parse("content://org.su.example.contentper"); ContentResolver contentResolver=getContentResolver(); contentResolver.query(uri,null,null,null,null); contentResolver.query(uri,null,null,null,null); contentResolver.delete(uri,null,null); contentResolver.delete(uri,null,null); } }
ContentResolver是android提供訪問ContentProvide的類。
日誌輸出
二、數據形式
ContentProvide的接口看起來就像數據庫的操作,增刪改查。ContentProvide的數據形式也多是組織成表格的形式。每個表有多列。表的一行代表一個記錄。這就意味著我們要使用一個ContentProvide還要知道它有哪些表,表結構是什麽樣的。一般android提供的ContentProvide都有一個說明類。例如訪問android的圖片的表結構可以通過MediaStore.Images獲得,聯系人信息通過ContactsContract.Contacts獲得。
三、自定義完整的ContentProvider
很多文章的表結構用的是book(id,name,author);
使用SQLiteOpenHelper
import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class DbOpenHelper extends SQLiteOpenHelper { private static final String DB_NAME = "book.db"; public static final String TABLE_NAME = "book"; private static final int DB_VERSION = 1; // book表 private String CREATE_BOOK_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(_id INTEGER PRIMARY KEY," + "name TEXT,"+" author TEXT)"; public DbOpenHelper(Context context) { super(context,DB_NAME,null,DB_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_BOOK_TABLE); } @Override public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion){ // TODO ignored } }
BookProvider代碼
import android.content.ContentProvider; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.util.Log; public class BookProvider extends ContentProvider { private static final String TAG = "BookProvider"; public static final String AUTHORITY = "org.su.book.provider"; public static final Uri URI = Uri.parse("content://" + AUTHORITY + "/book"); private Context mContext; private SQLiteDatabase mDb; @Override public boolean onCreate() { Log.d(TAG,"onCreate,current thread:"+ Thread.currentThread().getName()); mContext = getContext(); //初始化數據 initProviderData(); return true; } private void initProviderData() { mDb = new DbOpenHelper(mContext).getWritableDatabase(); mDb.execSQL("delete from " + DbOpenHelper.TABLE_NAME); mDb.execSQL("insert into book values(3,‘Android‘,‘Android‘);"); mDb.execSQL("insert into book values(4,‘Ios‘,‘Ios‘);"); mDb.execSQL("insert into book values(5,‘Html5‘,‘web‘);"); } @Override public Cursor query(Uri uri,String[] projection,String selection, String[] selectionArgs,String sortOrder) { String table = getTableName(uri); if (table == null) { throw new IllegalArgumentException("Unsupported URI: " + uri); } return mDb.query(table,projection,selection,selectionArgs,null, null,sortOrder,null); } @Override public String getType(Uri uri) { Log.d(TAG,"getType"); return null; } @Override public Uri insert(Uri uri,ContentValues values) { Log.d(TAG,"insert"); String table = getTableName(uri); if (table == null) { throw new IllegalArgumentException("Unsupported URI: " + uri); }mDb.insert(table,null,values); mContext.getContentResolver().notifyChange(uri,null); return uri; } @Override public int delete(Uri uri,String selection,String[] selectionArgs) { Log.d(TAG,"delete"); String table = getTableName(uri); if (table == null) { throw new IllegalArgumentException("Unsupported URI: " + uri); } int count = mDb.delete(table,selection,selectionArgs); if (count > 0) { getContext().getContentResolver().notifyChange(uri,null); } return count; } @Override public int update(Uri uri,ContentValues values,String selection, String[] selectionArgs) {Log.d(TAG,"update"); String table = getTableName(uri); if (table == null) { throw new IllegalArgumentException("Unsupported URI: " + uri); } int row = mDb.update(table,values,selection,selectionArgs); if (row > 0) { getContext().getContentResolver().notifyChange(uri,null); } return row; } private String getTableName(Uri uri) { String tableName = null; if(uri.equals(URI)) tableName=DbOpenHelper.TABLE_NAME; return tableName; } }
在MainActivity中訪問
Uri uri=Uri.parse("content://org.su.book.provider/book"); ContentResolver contentResolver=getContentResolver(); ContentValues values = new ContentValues(); values.put("_id",6); values.put("name","程序設計"); values.put("author","c"); contentResolver.insert(uri,values); Cursor bookCursor =contentResolver.query(uri,new String[] {"_id","name","author"},null,null,null); while (bookCursor.moveToNext()) { int id= bookCursor.getInt(0); String name = bookCursor.getString(1); String author =bookCursor.getString(2); Log.d(Tag,"query book:" +"id ="+id+",name ="+name+",author ="+author); } bookCursor.close();
日誌輸出:
四大組件初始之ContentProvider