码迷,mamicode.com
首页 > 移动开发 > 详细

Android之Content Provider学习使用

时间:2015-08-07 20:06:28      阅读:126      评论:0      收藏:0      [点我收藏+]

标签:

一、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进行声明(也可以用代码进行动态注册,生命周期会有所不同))

<!-- 注册ContentProvider -->
<!-- 使用authorities标记来设定Content Provider的基本URI,Content Provider的授权如同一个地址,
     Content Resolver使用它找到想要交互的数据库 -->
<!-- 一般URI的常用格式为com.<CompanyNanme>.provider.<ApplicationName> -->
<provider
    android:name=".MyContentProvider"
    android:authorities="com.paad.skeletondatabaseprovider"/>
3)实现ContentProvider,为外界提供一些列接口

Content Provider接受两种形式的URI,一种用来请求所有数据,另一种用来执行单独的一行。第二种形式会在基础URI后面机上行标识符(形式为/<rowID>)。

/**
 *  实现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<Cursor> loaderCallback = new LoaderManager.LoaderCallbacks<Cursor>() {
        /** 当Loader初始化时会被调用,最终创建并返回一个新的CursorLoader对象*/
        public Loader<Cursor> 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<Cursor> loader, Cursor cursor) {
            // @value SimpleCursorAdapter adapter
            // 用一个新的结果集代替Cursor Adapter所显示的结果Cursor
            adapter.swapCursor(cursor);
           
            // 这个处事程序不会和UI线程同步,因此在修改任意UI元素之前需要同步它
        }
 
        /** 当Loader Manager重置Cursor Loader时候,调用*/
        public void onLoaderReset(Loader<Cursor> loader) {
            // 在List Adapter中将现有的结果Cursor移除
            adapter.swapCursor(null);
           
            // 这个处事程序也不会和UI线程同步,因此在修改任意UI元素之前需要同步它
        }
    };
}

常见面试题:

1、 AndroidActivity, Intent, Content Provider, Service各有什么区别。

Activity: 活动,是最基本的android应用程序组件。一个活动就是一个用户可以操作的可视化用户界面,每一个活动都被实现为一个独立的类,并且从活动基类继承而来。
Intent: 意图,描述应用想干什么。最重要的部分是动作和动作对应的数据。
Content Provider:内容提供器,android应用程序能够将它们的数据保存到文件、SQLite数据库中,甚至是任何有效的设备中。当你想将你的应用数据和其他应用共享时,内容提供器就可以发挥作用了。
Service:服务,具有一段较长生命周期且没有用户界面的程序组件


版权声明:本文为博主原创文章,未经博主允许不得转载。

Android之Content Provider学习使用

标签:

原文地址:http://blog.csdn.net/woliuyunyicai/article/details/47341733

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!