Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android之Content Provider學習使用

Android之Content Provider學習使用

編輯:關於Android編程

一、SQLite數據庫使用

 

public class MyHoardDatabase {
 
    /**
     * SQLiteOpenHelper是一個抽象類,它是用來創建、打開和升級數據庫的最佳實踐模式
     */
    private static class HoardDBOpenHelper extends SQLiteOpenHelper {

        private static final String DATABASE_NAME = myDatabase.db;// 數據庫名
        private static final String DATABASE_TABLE = GoldHoards;  // 數據庫表名
        private static final intDATABASE_VERSION = 1;              // 數據庫版本
 
        // 創建數據庫語句
        private static final String DATABASE_CREATE = create table 
                + DATABASE_TABLE +  ( + KEY_ID
                +  integer primary key autoincrement, 
                + KEY_GOLD_HOARD_NAME_COLUMN +  text not null, 
                + KEY_GOLD_HOARDED_COLUMN +  float, 
                + KEY_GOLD_HOARD_ACCESSIBLE_COLUMN +  integer);;
 
        /** 構造函數*/
        public HoardDBOpenHelper(Context context, String name,
                CursorFactory factory, int version) {
            super(context, name, factory, version);
        }
 
        /** onCreate初始化函數,創建數據庫*/
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(DATABASE_CREATE);
        }
 
        /** 數據庫版本更新函數*/
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            // 這裡采取的方法時delete原來的數據庫,然後再重新創建數據庫
            db.execSQL(DROP TABLE IF IT EXISTS  + DATABASE_TABLE);
            onCreate(db);
        }
    }
   
    // 主鍵
    public static final String KEY_ID = _id;
 
    // 表名
    public static final String KEY_GOLD_HOARD_NAME_COLUMN = GOLD_HOARD_NAME_COLUMN;
    public static final String KEY_GOLD_HOARD_ACCESSIBLE_COLUMN = OLD_HOARD_ACCESSIBLE_COLUMN;
    public static final String KEY_GOLD_HOARDED_COLUMN = GOLD_HOARDED_COLUMN;
 
    // SQliteOpenHelper實例
    private HoardDBOpenHelper hoardDBOpenHelper;
 
    /** 構造函數*/
    public MyHoardDatabase(Context context) {
        // 創建SQLiteOpenHelper實例
        hoardDBOpenHelper = new HoardDBOpenHelper(context,
                HoardDBOpenHelper.DATABASE_NAME, null,
                HoardDBOpenHelper.DATABASE_VERSION);
    }
 
    /**
     * 關閉數據庫(這裡僅需將SQLiteOpenHelper close掉即可)
     * */
    public void closeDatabase() {
        hoardDBOpenHelper.close();
    }
 
    /**
     * 查詢數據庫,返回查詢結果Cursor
     * */
    private Cursor getAccessibleHoard() {
        // 需要獲取的字段名列表
        String[] result_columns = new String[] {
                               KEY_ID,
                               KEY_GOLD_HOARD_ACCESSIBLE_COLUMN,
                               KEY_GOLD_HOARDED_COLUMN };
 
        // Where條件語句
        String where = KEY_GOLD_HOARD_ACCESSIBLE_COLUMN + = + 1;
 
        // 其他一些限制參數
        String whereArgs[] = null;
        String groupBy = null;
        String having = null;
        String order = null;
 
        // 根據SQLiteOpenHelper獲取DataBase實例
        SQLiteDatabase db = hoardDBOpenHelper.getWritableDatabase();
        /** 根據語句查詢數據庫*/
        Cursor cursor = db.query(HoardDBOpenHelper.DATABASE_TABLE,
                result_columns, where, whereArgs, groupBy, having, order);
       
        // 返回結果Cursor
        return cursor;
    }
 
    /**
     * 解析查詢獲取到的結果Cursor
     * */
    public float getAverageAccessibleHoardValue() {
        // 掉用查詢函數
        Cursor cursor = getAccessibleHoard();
 
        /** 這裡是以獲取到所有對應GOLD_HOARDED_COLUMN的字段值,並計算平均數*/
        float totalHoard = 0f;
        float averageHoard = 0f;
 
        // 找出使用獲取的數據列GOLD_HOARDED_COLUMN對應的索引
        int GOLD_HOARDED_COLUMN_INDEX = cursor.getColumnIndexOrThrow(KEY_GOLD_HOARDED_COLUMN);
 
        /** 對Cursor進行遍歷*/
        while (cursor.moveToNext()) {
            // 獲取每一行對應的值
            float hoard = cursor.getFloat(GOLD_HOARDED_COLUMN_INDEX);
            totalHoard += hoard;
        }
 
        // 計算平均數
        float cursorCount = cursor.getCount();
        // 這裡是考慮除數為0的特殊情況
        averageHoard = cursorCount > 0 ? (totalHoard / cursorCount) : Float.NaN;
 
        // 使用完結果Cursor注意close
        cursor.close();
 
        return averageHoard;
    }
 
    /**
     * 向數據庫中插入添加數據操作
     * */
    public void addNewHoard(String hoardName, float hoardValue, boolean hoardAccessible) {
        // 每插入一個新行,需要構造一個ContentValues對象,並使用put方法來填充每個鍵值對
        ContentValues newValues = new ContentValues();
 
        // ContentValues填充鍵值對
        newValues.put(KEY_GOLD_HOARD_NAME_COLUMN, hoardName);
        newValues.put(KEY_GOLD_HOARDED_COLUMN, hoardValue);
        newValues.put(KEY_GOLD_HOARD_ACCESSIBLE_COLUMN, hoardAccessible);
 
        // 插入記錄的用法
        SQLiteDatabase db = hoardDBOpenHelper.getWritableDatabase();
        db.insert(HoardDBOpenHelper.DATABASE_TABLE, null, newValues);
    }
 
   
    /**
     * 更新數據庫操作
     * */
    public void updateHoardValue(int hoardId, float newHoardValue) {
        // 同理創建ContentValues對象
        ContentValues updatedValues = new ContentValues();
 
        // 對應需要更新的鍵值對進行賦值
        updatedValues.put(KEY_GOLD_HOARDED_COLUMN, newHoardValue);
       
        // 填寫Where條件語句
        String where = KEY_ID + = + hoardId;
        String whereArgs[] = null;
 
        // 實現更新數據庫的操作
        SQLiteDatabase db = hoardDBOpenHelper.getWritableDatabase();
        db.update(HoardDBOpenHelper.DATABASE_TABLE, updatedValues, where, whereArgs);
    }
 
    /**
     * 刪除數據庫中的行的操作
     * */
    public void deleteEmptyHoards() {
        // 條件語句
        String where = KEY_GOLD_HOARDED_COLUMN + = + 0;
        String whereArgs[] = null;
 
        // 刪除數據庫對應操作
        SQLiteDatabase db = hoardDBOpenHelper.getWritableDatabase();
        db.delete(HoardDBOpenHelper.DATABASE_TABLE, where, whereArgs);
    }
}
二、Content Provider

 

Content Provider提供一個接口用來發布數據,通過Cursor Resolver來使用該數據。其為存儲和獲取數據提供統一的借口,可以在不同應用程序之間共享數據。 它允許將數據的應用程序組件和底層的數據源分離開來,並提供了一種通用機制來允許一個應用程序共享他們的數據或者使用其他應用程序提供的數據。
1、基本概念 1)ContentProvider使用表的形式來組織數據
   無論數據的來源是什麼,ContentProvider都會認為是一種表,然後把數據組織成表格
2)ContentProvider提供的方法
   query:查詢
   insert:插入
   update:更新
   delete:刪除
   getType:得到數據類型
   onCreate:創建數據時調用的回調函數
3)每個ContentProvider都有一個公共的URI,這個URI用於表示這個ContentProvider所提供的數據。Android所提供的ContentProvider都存放在android.provider包當中

2、Content Provider使用 1)繼承ContentProvider類實現ContentProvider 2)在manifest中注冊content provider(四大組件都需要在manifest進行聲明(也可以用代碼進行動態注冊,生命周期會有所不同))

 




3)實現ContentProvider,為外界提供一些列接口

 

Content Provider接受兩種形式的URI,一種用來請求所有數據,另一種用來執行單獨的一行。第二種形式會在基礎URI後面機上行標識符(形式為/)。

 

/**
 *  實現Content Provider,提供query,insert,update等一系列數據庫操作供
 *  Content Resolver來使用
 * 
 *  其實實現上有前面使用SQLite數據庫模式相仿,這裡是為外界提供一系列操作數據庫的接口
 *  */
public class MyContentProvider extends ContentProvider {
 
    /** 每個Content Provider都應該使用一個公有的靜態CONTENT_URI屬性來公開它的授權,使其容易被找到
     *  而這個Content Provider應該包含一個主要內容的數據路徑*/
    public static final Uri CONTENT_URI =
            Uri.parse(content://com.paad.skeletondatabaseprovider/elements);
 
    // 不同查詢方式的標志
    private static final intALLROWS = 1;
    private static final intSINGLE_ROW = 2;
 
    // 使用URriMatcher來區分不同的URI請求:是針對所有數據進行請求,還是僅請求單行數據
    private static final UriMatcher uriMatcher;
 
    // 添加匹配規則
    static {
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(com.paad.skeletondatabaseprovider, elements, ALLROWS);
        uriMatcher.addURI(com.paad.skeletondatabaseprovider, elements/#, SINGLE_ROW);
    }
 
    public static final String KEY_ID = _id;
    public static final String KEY_COLUMN_1_NAME = KEY_COLUMN_1_NAME;
 
    private MySQLiteOpenHelper myOpenHelper;
 
    @Override
    public boolean onCreate() {
        // 創建SQLiteOpenHelper實例
        myOpenHelper = new MySQLiteOpenHelper(getContext(),
                MySQLiteOpenHelper.DATABASE_NAME, null,
                MySQLiteOpenHelper.DATABASE_VERSION);
 
        return true;
    }
 
    /** 提供query操作
     *  數據庫查詢操作
     */
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
 
        // 獲得數據庫實例
        SQLiteDatabase db;
        try {
            db = myOpenHelper.getWritableDatabase();
        } catch (SQLiteException ex) {
            db = myOpenHelper.getReadableDatabase();
        }
 
        // WHERE條件語句
        String groupBy = null;
        String having = null;
 
        /** 使用SQLiteQueryBuilder來簡化構造數據查詢的過程**/
        SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
 
        // 通過URIMatcher來匹配URI,並對URI進行解析
        // 如果是單行查詢,則需要獲得查詢的是哪一行
        switch (uriMatcher.match(uri)) {
        case SINGLE_ROW:
            String rowID = uri.getPathSegments().get(1);
            queryBuilder.appendWhere(KEY_ID + = + rowID);
        default:
            break;
        }
 
        // 設置需要查詢的table的名稱
        queryBuilder.setTables(MySQLiteOpenHelper.DATABASE_TABLE);
 
        /** 執行查詢操作語句*/
        Cursor cursor = queryBuilder.query(db, projection, selection,
                selectionArgs, groupBy, having, sortOrder);
 
        return cursor;
    }
 
    /** 提供getType操作
     *  根據URI類型返回一個正確的Content Provider MIME類型數據
     */
    @Override
    public String getType(Uri uri) {
        switch (uriMatcher.match(uri)) {
        case ALLROWS:
            return vnd.android.cursor.dir/vnd.paad.elemental;
        case SINGLE_ROW:
            return vnd.android.cursor.item/vnd.paad.elemental;
        default:
            throw new IllegalArgumentException(Unsupported URI:  + uri);
        }
    }
 
    /** 提供delete操作
     *  執行刪除操作
     */
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // 打開數據庫
        SQLiteDatabase db = myOpenHelper.getWritableDatabase();
 
        // 匹配URI
        switch (uriMatcher.match(uri)) {
        case SINGLE_ROW:
            String rowID = uri.getPathSegments().get(1);
            selection = KEY_ID
                    + =
                    + rowID
                    + (!TextUtils.isEmpty(selection) ?  AND ( + selection
                            + ')' : );
        default:
            break;
        }
 
        if (selection == null)
            selection = 1;
 
        // 執行刪除操作
        int deleteCount = db.delete(MySQLiteOpenHelper.DATABASE_TABLE,
                selection, selectionArgs);
 
        // 通知有數據
        getContext().getContentResolver().notifyChange(uri, null);
 
        return deleteCount;
    }
 
    /**
     * 提供insert操作
     * */
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        SQLiteDatabase db = myOpenHelper.getWritableDatabase();
        String nullColumnHack = null;
 
        // 執行insert操作
        long id = db.insert(MySQLiteOpenHelper.DATABASE_TABLE, nullColumnHack, values);
 
        // 若擦如操作成功
        if (id > -1) {
            // 返回CONTENT_URI+最新插入的行ID
            Uri insertedId = ContentUris.withAppendedId(CONTENT_URI, id);
            // 通知數據變更
            getContext().getContentResolver().notifyChange(insertedId, null);
            return insertedId;
        } else
            return null;
    }
 
    /** 提供insert操作*/
    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        SQLiteDatabase db = myOpenHelper.getWritableDatabase();
 
        // 判斷URI是否匹配
        switch (uriMatcher.match(uri)) {
        case SINGLE_ROW:
            String rowID = uri.getPathSegments().get(1);
            selection = KEY_ID
                    + =
                    + rowID
                    + (!TextUtils.isEmpty(selection) ?  AND ( + selection
                            + ')' : );
        default:
            break;
        }
 
        int updateCount = db.update(MySQLiteOpenHelper.DATABASE_TABLE, values,
                selection, selectionArgs);
 
        getContext().getContentResolver().notifyChange(uri, null);
 
        return updateCount;
    }
 
    /**
     * 同前面提到的使用SQLiteOpenHelper來操作數據庫
     **/
    private static class MySQLiteOpenHelper extends SQLiteOpenHelper {
 
        private static final String DATABASE_NAME = myDatabase.db;
        private static final int DATABASE_VERSION = 1;
        private static final String DATABASE_TABLE = mainTable;
 
        private static final String DATABASE_CREATE = create table 
                + DATABASE_TABLE +  ( + KEY_ID
                +  integer primary key autoincrement,  + KEY_COLUMN_1_NAME
                +  text not null);;
 
        public MySQLiteOpenHelper(Context context, String name,
                CursorFactory factory, int version) {
            super(context, name, factory, version);
        }
 
        @Override
        public void onCreate(SQLiteDatabase _db) {
            _db.execSQL(DATABASE_CREATE);
        }
 
        @Override
        public void onUpgrade(SQLiteDatabase _db, int _oldVersion,
                int _newVersion) {
            _db.execSQL(DROP TABLE IF IT EXISTS  + DATABASE_TABLE);
            onCreate(_db);
        }
    }
}

 

 

4、使用Content Resolver: 每一個應用程序都有一個ContentResolver實例,可以使用getContentResolver方法來對其進行訪問:
  ContentResolver contentResolver = this.getContentResolver();

 

使用實例:

 

public class DatabaseSkeletonActivity extends Activity {
 
    static final String TAG = DATABASESKELETONACTIVITY;
    private SimpleCursorAdapter adapter;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        // Use the Search Manager to find the SearchableInfo related
        // to this Activity.
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchableInfo searchableInfo = searchManager
                .getSearchableInfo(getComponentName());
 
        // Bind the Activity's SearchableInfo to the Search View
        SearchView searchView = (SearchView) findViewById(R.id.searchView);
        searchView.setSearchableInfo(searchableInfo);
    }
 
    /**
     * 查詢數據庫,查詢所有行的情況
     **/
    private String getLargestHoardName() {
        // 獲得ContentResolver實例
        ContentResolver cr = getContentResolver();
 
        // 需要查詢的字段名
        String[] result_columns = new String[] { MyHoardContentProvider.KEY_ID,
                MyHoardContentProvider.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN,
                MyHoardContentProvider.KEY_GOLD_HOARDED_COLUMN };
 
        // 查詢限制語句
        String where = MyHoardContentProvider.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN + = + 1;
        String whereArgs[] = null;
        String order = null;
 
        /** 執行查詢語句*/
        Cursor resultCursor = cr.query(MyHoardContentProvider.CONTENT_URI,
                result_columns, where, whereArgs, order);
 
        /** 解析查詢結果Cursor,類似於前面使用SQLite數據庫查詢的流程*/
        float largestHoard = 0f;
        String hoardName = No Hoards;
 
        int GOLD_HOARDED_COLUMN_INDEX = resultCursor
                .getColumnIndexOrThrow(MyHoardContentProvider.KEY_GOLD_HOARDED_COLUMN);
        int HOARD_NAME_COLUMN_INDEX = resultCursor
                .getColumnIndexOrThrow(MyHoardContentProvider.KEY_GOLD_HOARD_NAME_COLUMN);
 
        while (resultCursor.moveToNext()) {
            float hoard = resultCursor.getFloat(GOLD_HOARDED_COLUMN_INDEX);
            if (hoard > largestHoard) {
                largestHoard = hoard;
                hoardName = resultCursor.getString(HOARD_NAME_COLUMN_INDEX);
            }
        }
 
        // 使用完畢注意關閉Cursor
        resultCursor.close();
        return hoardName;
    }
 
    /**
     * 查詢單一某一行的情況
     **/
    private Cursor getRow(long rowId) {
        ContentResolver cr = getContentResolver();
        String[] result_columns = new String[] { MyHoardContentProvider.KEY_ID,
                MyHoardContentProvider.KEY_GOLD_HOARD_NAME_COLUMN,
                MyHoardContentProvider.KEY_GOLD_HOARDED_COLUMN };
 
        // 填充URI
        Uri rowAddress = ContentUris.withAppendedId(
                MyHoardContentProvider.CONTENT_URI, rowId);
 
        String where = null;
        String whereArgs[] = null;
        String order = null;
 
        /** 執行查詢操作**/
        Cursor resultCursor = cr.query(rowAddress, result_columns, where, whereArgs, order);
 
        return resultCursor;
    }
 
    /** 數據庫添加insert操作*/
    private Uri addNewHoard(String hoardName, float hoardValue, boolean hoardAccessible) {
        ContentValues newValues = new ContentValues();
 
        // 填充鍵值對
        newValues.put(MyHoardContentProvider.KEY_GOLD_HOARD_NAME_COLUMN, hoardName);
        newValues.put(MyHoardContentProvider.KEY_GOLD_HOARDED_COLUMN, hoardValue);
        newValues.put(MyHoardContentProvider.KEY_GOLD_HOARD_ACCESSIBLE_COLUMN, hoardAccessible);
 
        /** 通過ContentResolver來操作數據庫*/
        ContentResolver cr = getContentResolver();
        Uri myRowUri = cr.insert(MyHoardContentProvider.CONTENT_URI, newValues);
        return myRowUri;
    }
 
    /** 刪除操作*/
    private int deleteEmptyHoards() {
        String where = MyHoardContentProvider.KEY_GOLD_HOARDED_COLUMN + = + 0;
        String whereArgs[] = null;
        ContentResolver cr = getContentResolver();
        int deletedRowCount = cr.delete(MyHoardContentProvider.CONTENT_URI, where, whereArgs);
        return deletedRowCount;
    }
 
    /** 更新操作*/
    private int updateHoardValue(int hoardId, float newHoardValue) {
        ContentValues updatedValues = new ContentValues();
        updatedValues.put(MyHoardContentProvider.KEY_GOLD_HOARDED_COLUMN, newHoardValue);
        Uri rowURI = ContentUris.withAppendedId(MyHoardContentProvider.CONTENT_URI, hoardId);
        String where = null;
        String whereArgs[] = null;
 
        ContentResolver cr = getContentResolver();
        int updatedRowCount = cr.update(rowURI, updatedValues, where, whereArgs);
        return updatedRowCount;
    }
   
    /** 使用Cursor Loader異步查詢內容
     *  數據庫操作可能是非常耗時的,所以對於任何數據庫和ContentProvider查詢而言,最好不要在應用程序的主線程中執行
     *  較好的實現方式是使用Loader類,Loader被設計用來異步加載數據和監控底層數據源的變化
     **/
    LoaderManager.LoaderCallbacks loaderCallback = new LoaderManager.LoaderCallbacks() {
        /** 當Loader初始化時會被調用,最終創建並返回一個新的CursorLoader對象*/
        public Loader onCreateLoader(int id, Bundle args) {
            String[] projection = null;
            String where = null;
            String[] whereArgs = null;
            String sortOrder = null;
 
            Uri queryUri = MyContentProvider.CONTENT_URI;
 
            return new CursorLoader(DatabaseSkeletonActivity.this, queryUri,
                    projection, where, whereArgs, sortOrder);
        }
 
        /** 當Loader Manager完成異步查詢後,調用*/
        public void onLoadFinished(Loader loader, Cursor cursor) {
            // @value SimpleCursorAdapter adapter
            // 用一個新的結果集代替Cursor Adapter所顯示的結果Cursor
            adapter.swapCursor(cursor);
           
            // 這個處事程序不會和UI線程同步,因此在修改任意UI元素之前需要同步它
        }
 
        /** 當Loader Manager重置Cursor Loader時候,調用*/
        public void onLoaderReset(Loader loader) {
            // 在List Adapter中將現有的結果Cursor移除
            adapter.swapCursor(null);
           
            // 這個處事程序也不會和UI線程同步,因此在修改任意UI元素之前需要同步它
        }
    };
}

常見面試題:

 

1、 Android中Activity, Intent, Content Provider, Service各有什麼區別。

Activity: 活動,是最基本的android應用程序組件。一個活動就是一個用戶可以操作的可視化用戶界面,每一個活動都被實現為一個獨立的類,並且從活動基類繼承而來。
Intent: 意圖,描述應用想干什麼。最重要的部分是動作和動作對應的數據。
Content Provider:內容提供器,android應用程序能夠將它們的數據保存到文件、SQLite數據庫中,甚至是任何有效的設備中。當你想將你的應用數據和其他應用共享時,內容提供器就可以發揮作用了。
Service:服務,具有一段較長生命周期且沒有用戶界面的程序組件。


 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved