浅析 - Android ContentProvider用法示例
来源:互联网 发布:淘宝分销模式解说 编辑:程序博客网 时间:2024/06/05 16:21
尊重每个人的付出,转载请点这里: http://blog.csdn.net/hanj456/article/details/52621150
作为Android的四大组件之一,也许你平时开发中根本没有用到过ContentProvider,但你还是需要掌握它的一些基本操作步骤,任何看起来挺复杂的东西拆开来看就那么回事,下面还是先进入我们的“三问三答”环节:
ContentProvider之“三问三答”
问:ContentProvider是什么?
答:Android四大组件之一(Activity ,Service , BroadcastReceiver ,ContentProvider),向我们提供了在不同应用程序之间共享数据的一种机制,统一了应用之间数据访问的方式。
问:ContentProvider的作用?
答:简单来说它的作用就是为不同应用之间存储和获取数据提供了统一的接口,比较常用到的是共享视频,音频,图片,通讯录这些资源。
问:ContentProvider如何使用?
答:因为相比其他三个组件来说它不常用到,而且看到继承ContentProvider需要实现六个方法,很多人一下子被吓到了,其实仔细看会发现除去对数据基本的增删改查和onCreate()外,也就剩下一个getType()没见过的方法,这样分析下来是不是就感觉轻松很多呢?其实要掌握ContentProvider的基本用法主要记住以下四个API的用法就行:
- UriMatcher.match() //主要是对Uri进行匹配;
- ContentResolver.notifyChange() //主要是对数据进行刷新;
- ContentUris.parseId() //主要是对Uri进行解析;
- ContentUris.withAppendedId() //主要是给Uri添加ID
下面我将以一个简单的Demo为例,分解说明使用ContentProvider实现不同应用之间数据 共享操作需要哪些步骤:
有两个应用:应用A(获取操作数据的一方)和应用B(共享数据的一方)
Step1
在应用B中创建数据资源,这里我新建一个sqlite表 students,添加_id , name , age三个字段:
public class DBHelper extends SQLiteOpenHelper { private static SQLiteOpenHelper mInstance; public synchronized static SQLiteOpenHelper getInstance(Context context){ if (mInstance==null){ mInstance = new DBHelper(context,"test.db",null,1); } return mInstance; } private DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE students(_id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT,age INTEGER)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }}
Step2
新建一个常量类,提前准备几个需要用到的常量数据
public class Const { public static final String TABLE_NAME = "students"; public static final String AUTHORITY = "com.test.provider2"; public static final class Student implements BaseColumns { public static final String ID = "_id"; public static final String NAME = "name"; public static final String AGE = "age"; public static final Uri DIR_STUDENTS_URI = Uri.parse("content://" + AUTHORITY + "/students"); public static final Uri ITEM_STUDENT_URI = Uri.parse("content://" + AUTHORITY + "/student"); }}
Step3
新建一个ContentProvider子类继承ContentProvider
public class MyProvider extends ContentProvider { private static UriMatcher mMatcher = new UriMatcher(UriMatcher.NO_MATCH); private static final int STUDENTS = 1; private static final int STUDENT = 2; static { mMatcher.addURI(Const.AUTHORITY, "students", STUDENTS); mMatcher.addURI(Const.AUTHORITY, "student/#", STUDENT); } private SQLiteOpenHelper mHelper; private ContentResolver mResolver; @Override public boolean onCreate() { mHelper = DBHelper.getInstance(getContext()); mResolver = getContext().getContentResolver(); return true;//设置为true表示provider创建生效 } @Nullable @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = mHelper.getReadableDatabase(); switch (mMatcher.match(uri)) { case STUDENTS: return db.query(Const.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder); case STUDENT: long id = ContentUris.parseId(uri); String condition = Const.Student.ID + "=" + id; if (selection != null && !selection.equals("")) { condition = condition + " and " + selection; } return db.query(Const.TABLE_NAME, projection, condition, selectionArgs, null, null, sortOrder); default: throw new IllegalArgumentException("未知的Uri:" + uri); } } @Nullable @Override public String getType(Uri uri) { switch (mMatcher.match(uri)) { case STUDENTS: return "vnd.android.cursor.dir/com.test.provider2"; //前半部分是规定的写法,表示这是一个查询全部数据的类型,后半部分是自定义的 case STUDENT: return "vnd.android.cursor.item/com.test.provider2";//前半部分是规定的写法,表示这是一个查询单条数据的类型,后半部分是自定义的 default: throw new IllegalArgumentException("未知的Uri:" + uri); } } @Nullable @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = mHelper.getWritableDatabase(); if (mMatcher.match(uri) != STUDENTS) { throw new IllegalArgumentException("未知的Uri:" + uri); } long id = db.insert(Const.TABLE_NAME, Const.Student.ID, values); if (id < 0) { throw new SQLiteException("插入数据失败!"); } Uri newUri = ContentUris.withAppendedId(uri, id); mResolver.notifyChange(uri, null); return newUri; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = mHelper.getWritableDatabase(); int deleteNum = -1; switch (mMatcher.match(uri)) { case STUDENTS: deleteNum = db.delete(Const.TABLE_NAME, selection, selectionArgs); break; case STUDENT: long id = ContentUris.parseId(uri); String condition = Const.Student.ID + "=" + id; if (selection != null && !selection.equals("")) { condition = condition + " and " + selection; } deleteNum = db.delete(Const.TABLE_NAME, condition, selectionArgs); break; default: throw new IllegalArgumentException("未知的Uri:" + uri); } mResolver.notifyChange(uri,null); return deleteNum; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase db = mHelper.getWritableDatabase(); int updateNum = -1; switch (mMatcher.match(uri)) { case STUDENTS: updateNum = db.update(Const.TABLE_NAME, values, selection, selectionArgs); break; case STUDENT: long id = ContentUris.parseId(uri); String condition = Const.Student.ID + "=" + id; if (selection != null && !selection.equals("")) { condition = condition + " and " + selection; } updateNum = db.update(Const.TABLE_NAME, values, condition, selectionArgs); break; default: throw new IllegalArgumentException("未知的Uri:" + uri); } mResolver.notifyChange(uri,null); return updateNum; }}
Step4
在清单文件中配置provider
<provider android:authorities="com.test.provider2" android:name=".second.MyProvider" android:exported="true"/>//设置为true表示允许对外共享数据
Step5
经过上面5步ContentProvider的基本步骤就算完成了,剩下的就是在应用A中去获取和操作应用B中的数据了,因为要获取应用B中的数据,必须知道ContentProvider中对外提供的字段,也就是应用B中的常量数据,所以最好先把该常量类Const.java 拷贝到应用A中方便使用,应用A中MainActivity 布局文件很简单,就只有四个按钮分别对应:增,删,改,查;
public class MainActivity extends AppCompatActivity { private ContentResolver mResolver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mResolver = getContentResolver(); } public void add(View v){ ContentValues values = new ContentValues(); values.put(Const.Student.NAME,"小明"); values.put(Const.Student.AGE,16); mResolver.insert(Const.Student.DIR_STUDENTS_URI,values); values.put(Const.Student.NAME,"小强"); values.put(Const.Student.AGE,17); mResolver.insert(Const.Student.DIR_STUDENTS_URI,values); Toast.makeText(this,"添加数据成功",Toast.LENGTH_SHORT).show(); } public void update(View v){ ContentValues values = new ContentValues(); values.put(Const.Student.AGE,28); mResolver.update(Const.Student.DIR_STUDENTS_URI,values,"name like ?",new String[]{"小明"}); Toast.makeText(this,"更新数据成功",Toast.LENGTH_SHORT).show(); } public void delete(View v){ mResolver.delete(Const.Student.DIR_STUDENTS_URI,"name like ?",new String[]{"小明"}); Toast.makeText(this,"删除数据成功",Toast.LENGTH_SHORT).show(); } public void query(View v){ Cursor cursor = mResolver.query(Const.Student.DIR_STUDENTS_URI, null, null, null, null); int count = cursor.getCount(); if (count<1){ Toast.makeText(this,"数据为空!",Toast.LENGTH_SHORT).show(); return; } while (cursor.moveToNext()){ String name = cursor.getString(1); String age = cursor.getString(2); Toast.makeText(this,"name="+name+" ,age="+age,Toast.LENGTH_SHORT).show(); } }}
好了,到此应用A通过ContentProvider操作应用B中的数据实验成功,这里我主要是讲使用ContentProvider的基本步骤,至于上面所提到的那几个API的细节大家有兴趣可以花点时间去查看官方文档说明,理清楚思路很重要,很多东西都没有看上去那么难!
- 浅析 - Android ContentProvider用法示例
- ContentProvider的用法浅析
- Android ContentProvider基本用法
- android中ContentProvider+ContentResolver示例
- Android中ContentProvider的用法
- android 之 service+contentProvider 音乐播放示例
- Android 之 ContentProvider (二) 示例代码
- ContentProvider示例
- ContentPRovider示例
- Android 中ContentProvider的用法及用ContentProvider访问联系人
- Android 中ContentProvider的用法及用ContentProvider访问联系人
- Android rxjava用法浅析
- 浅析 - Sqlite的用法和示例
- Android中ContentProvider和Uri用法
- Android中ContentProvider和Uri用法
- Android中ContentProvider和Uri用法!!
- Android中ContentProvider和Uri用法
- Android中ContentProvider和Uri用法
- 实现类似新浪微博、QQ空间等帖子显示(1)——SpannableString说明
- 升级到android studio 2.2项目死活run不起来
- Easy 27题 Remove Element
- 在Ubuntu-14.04.3配置并成功编译Android6_r1源码
- 记录一个decimal格式转换出现的问题
- 浅析 - Android ContentProvider用法示例
- 前端基础——CSS常见样式
- Android SensorService启动流程(一)
- CentOS 6.3下部署LVS(NAT)+keepalived实现高性能高可用负载均衡
- Majority Element
- OpenNI2 开发者指南
- oracle优化
- xib 修改约束,参数没反应
- 如何查看linux版本 如何查看LINUX是多少位