安卓存儲數據和文件系列4:內容提供者(Content Provider)方式

內容提供者(Content Provider)是android的四大組件之一,重要性可想而知,一個進程的數據可以被另外一個進程訪問(在不同的apk之間可以訪問),內容提供者可以跨應用,數據庫跨應用的使用場景:一個應用中提供數據給其他應用;允許用戶從一個應用中拷貝數據到另一個應用;在整個框架中提供一種自定義的查詢建議。如果只在一個應用中使用數據的話使用SQLite,不需要使用Content Provider。

整體思路:創建一個繼承SQLiteOpenHelper的DbHelper類,在這個類中聲明數據庫名稱和版本號碼,在onCreate方法中寫創建表的sql語句並執行,onUpgrade方法中暫時不做任何操作(目前不涉及升級數據庫的操作)。創建一個繼承ContentProvider的StudentProvider類,在這個類中定義一個默認不匹配的UriMatcher對象,聲明兩個標誌位,聲明一個靜態代碼塊,在這個代碼塊中定義兩個匹配規則,定義一個getType方法,在這個方法中根據不同的標記返回不同的類型,在這個類中定義增刪改查操作對應的方法,在這些方法中根據不同的標記來執行單條記錄和多條記錄的操作。創建一個繼承AndroidTestCase的MyTest單元測試類,在這個類中定義增刪改查方法,在這些方法中定義一個內容解析者,使用內容解析者調用操作數據庫的方法。注意:在清單文件AndroidManifest.xml文件中註冊內容提供者和註冊測試單元。創建另一個工程,在這個工程中將MyTest類複製過來,運行裏面的各個方式進行測試。這樣就完成了從一個工程向另一個工程中訪問數據的操作。

DbHelper.java文件:

public class DbHelper extends SQLiteOpenHelper {

	private static String name="mydb.db";
	private static int version=1;//初始的版本號是1
	public DbHelper(Context context) {
		super(context, name, null, version);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void onCreate(SQLiteDatabase database) {
		// TODO Auto-generated method stub
        String sql="create table student (id integer primary key autoincrement ,name varchar(64),address varchar(64))";
        database.execSQL(sql);//對數據庫表的創建
	}

	@Override
	public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
		// TODO Auto-generated method stub

	}

}
StudentProvider.java文件:

//ContentProvider是一個抽象類,需要聲明一個類去繼承它,分別去重寫增刪改查的方法
public class StudentProvider extends ContentProvider {

	private final String TAG = "StudentProvider";
	private DbHelper helper = null;

	// 默認是不匹配
	private static final UriMatcher URI_MATCHER = new UriMatcher(
			UriMatcher.NO_MATCH);
	// 聲明兩個標誌位
	private static final int STUDENT = 1;// 表示操作單條記錄
	private static final int STUDENTS = 2;// 表示操作多條記錄

	// 聲明一個靜態的代碼模塊
	static {
		// 定義了兩個匹配規則
		URI_MATCHER.addURI(
				"com.example.android_contentprovider.StudentProvider",
				"student", STUDENTS);

		URI_MATCHER.addURI(
				"com.example.android_contentprovider.StudentProvider",
				"student/#", STUDENT);

	}

	public StudentProvider() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		// TODO Auto-generated method stub
		int count = -1;// 表示影響數據庫的行數
		try {
			int flag = URI_MATCHER.match(uri);
			SQLiteDatabase database = helper.getWritableDatabase();
			switch (flag) {
			case STUDENT:// 單條記錄
				// delete from student where id=? id是通過客戶端傳遞過來的
				long id = ContentUris.parseId(uri);
				String where_value = "id=" + id;
				if (selection != null && !selection.equals("")) {
					where_value += " and " + selection;
				}
				count = database.delete("student", where_value, selectionArgs);
				break;

			case STUDENTS:// 多條記錄
				count = database.delete("student", selection, selectionArgs);
				break;
			}

		} catch (Exception e) {
			// TODO: handle exception
		}
		return count;
	}

	@Override
	public String getType(Uri uri) {
		// TODO Auto-generated method stub
		int flag = URI_MATCHER.match(uri);
		switch (flag) {
		case STUDENT:
			return "vnd.android.cursor.item/student";
		case STUDENTS:
			return "vnd.android.cursor.dir/students";
		}
		return null;
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		// TODO Auto-generated method stub
		// insert into student() (?,?);
		Uri resultUri = null;
		int flag = URI_MATCHER.match(uri);// 外部傳遞進來的uri來匹配內部的規則
		switch (flag) {
		case STUDENTS:
			SQLiteDatabase database = helper.getWritableDatabase();
			// 返回插入當前行的行號
			long id = database.insert("student", null, values);
			resultUri = ContentUris.withAppendedId(uri, id);
			break;
		}
		Log.i(TAG, "-->>" + resultUri.toString());
		return resultUri;
	}

	@Override
	public boolean onCreate() {
		// TODO Auto-generated method stub
		helper = new DbHelper(getContext());
		return false;
	}

	@Override
	public Cursor query(Uri uri, String[] arg1, String selection,
			String[] selectionArgs, String arg4) {
		// TODO Auto-generated method stub
		Cursor cursor = null;
		try {
			SQLiteDatabase database = helper.getReadableDatabase();
			int flag = URI_MATCHER.match(uri);// 匹配路徑
			switch (flag) {
			case STUDENT:// 查詢返回單條記錄
				long id = ContentUris.parseId(uri);
				String where_value = " id = " + id;
				if (selection != null && !selection.equals("")) {
					where_value += " and " + selection;
				}
				cursor = database.query("student", null, where_value,
						selectionArgs, null, null, null, null);
				break;

			case STUDENTS:// 查詢返回多條記錄
				cursor = database.query("student", null, selection,
						selectionArgs, null, null, null, null);
				break;
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return cursor;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		// TODO Auto-generated method stub
		int count = -1;
		try {
			// update table set name= ?,address= ? where id = ?
			SQLiteDatabase database = helper.getWritableDatabase();
			long id = ContentUris.parseId(uri);
			int flag = URI_MATCHER.match(uri);
			switch (flag) {
			case STUDENT:
				String where_value = " id= " + id;
				if (selection != null && !selection.equals("")) {
					where_value += " and " + selection;
				}
				count = database.update("student", values, where_value,
						selectionArgs);
				break;
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return count;
	}

}
MyTest.java文件:
public class MyTest extends AndroidTestCase {

	public MyTest() {
		// TODO Auto-generated constructor stub
	}
	
	public void insert(){
//		訪問內容提供者的步驟:
//		1.需要一個內容解析者
		ContentResolver contentResolver=getContext().getContentResolver();
//		使用content://+授權路徑  來訪問一個內容提供者
		Uri url=Uri.parse("content://com.example.android_contentprovider.StudentProvider/student");
		ContentValues values=new ContentValues();
		values.put("name", "吳孟達");
		values.put("address", "香港");
		contentResolver.insert(url, values);
		
	}
	
	public void delete(){
//		內容解析者
		ContentResolver contentResolver=getContext().getContentResolver();
//		刪除第一條記錄,在後面需要加/1
//		刪除多條記錄,後面不加任何東西
		Uri url=Uri.parse("content://com.example.android_contentprovider.StudentProvider/student/1");
		contentResolver.delete(url, null, null);
	}
	
	public void update(){
//		得到一個內容解析者
		ContentResolver contentResolver=getContext().getContentResolver();
		Uri uri=Uri.parse("content://com.example.android_contentprovider.StudentProvider/student/2");
		ContentValues values=new ContentValues();
		values.put("name", "美人魚");
		values.put("address", "香港");
		contentResolver.update(uri, values, null, null);
	}
	
	public void query(){
		ContentResolver contentResolver=getContext().getContentResolver();
//		查詢單條記錄(查詢id爲2的那條記錄):content://com.example.android_contentprovider.StudentProvider/student/2
//		查詢多條記錄:content://com.example.android_contentprovider.StudentProvider/student
//		Uri uri=Uri.parse("content://com.example.android_contentprovider.StudentProvider/student/2");
		Uri uri=Uri.parse("content://com.example.android_contentprovider.StudentProvider/student");
//		相當於這樣的sql語句:select * from student where id =2;
		Cursor cursor=contentResolver.query(uri, null, null, null, null);
		while (cursor.moveToNext()) {
			System.out.println("-->>"+cursor.getString(cursor.getColumnIndex("name"))+"  "+cursor.getString(cursor.getColumnIndex("address")));
		}
	}

}
AndroidManifest.xml文件:

   <instrumentation android:targetPackage="com.example.android_contentprovider" android:name="android.test.InstrumentationTestRunner"></instrumentation>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <uses-library android:name="android.test.runner"/>
        <activity
            android:name="com.example.android_contentprovider.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- 定義了一個內容提供者   authorities是授權:包名加類名             android:exported="true"-->
        <provider 
            android:exported="true"
            android:name=".StudentProvider" android:authorities="com.example.android_contentprovider.StudentProvider" 
            ></provider>
    </application>




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章