android 四大组件之ContentProvider
2017-05-04 22:54
316 查看
ContentProvider是android四大组件之一,从名字可以看出,就是内容提供者,让其他app可以访问到该应用暴露的数据,实际上也是如此,一般情况下,不会用到ContentProvider,但是获取联系人,也就间接的使用到了,下面简单介绍下ContentProvider的使用
1.创建一个ContentProvider的实现类:
新建一个类并继承ContentProvider的类,四大组件都是如此做的,ContentProvider是一个抽象类, 有六个抽象方法 onCreate、getType、delete、update、insert和query,并从写这六个方法
看到delete、update、insert和query这些方法,刚好对应着数据的增删改查四个方法,这些用于供外部应用往ContentProvider增删改查数据,其实的确如此。onCreate方法,该方法在ContentProvider创建后就会被调用,Android开机后,ContentProvider在其它应用第一次访问它时才会被创建,getType方法,该方法用于返回当前Url所代表数据的MIME类型
getType方法
1)如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头,
例如:要得到所有person记录的Uri为content://com.app.wurui.providerdemo.myprovider/person,那么返回的MIME类型字符串应该为:”vnd.android.cursor.dir/person”。
2)如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头,
例如:得到id为10的person记录,Uri为content://com.app.wurui.providerdemo.myprovider/person/10,那么返回的MIME类型字符串为:”vnd.android.cursor.item/person”
2.注册
也是在<\application>节点下进行注册
3.外部访问地址
1)、每一个ContentProvider都拥有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据
2)、Android所提供的ContentProvider都存放在android.provider包中。 将其分为A,B,C,D 4个部分,也可以使用三部分,去掉D部分:
A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;”content://”
B:URI 的标识,用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。这个标识在 元素的 authorities属性中说明:一般是定义该ContentProvider的包.类的名称
C:路径(path),通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就可以了; “content://com.app.wurui.providerdemo.myprovider/person/1”
D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部; “content://com.app.wurui.providerdemo.myprovider/person/tablename/#” #表示数据id
4.UriMatcher类和ContentUris类介绍
在应用ContentProvider之前,先了解俩个类,是android系统专门为ContentProvider提供解析Uri的工具类
1).UriMatcher类
该类提供了两个方法,addURI 和match方法,主要用于匹配Uri
2).ContentUris类
该类提供了三个静态方法,withAppendedId、parseId和appendId方法
上面几个方法,注释写的很清楚,在此不在解释了
5.ContentProvider的简单实例 这里用数据库来存储数据
此处不介绍数据库
ContentProvider就写好了,为了验证是否正确,在另一个app调用
以上就简单实现了ContentProvider的实例
6.监听ContentProvider中数据的变化
1.继承ContentObserver类,并重写onChange方法
2.1注册对指定Uri的监听函数,一旦该Uri指向的内容发生改变,将通知到MyObserver类的onChange方法
2.2当程序退出或者不需要再监听Uri的变化时,要主动取消对Uri的监听
3.在ContentProvider里,每当特定Uri上的数据发生变化,要触发对调用者对通知。通知使用ContentResolver的notifyChange()方法触发。比如删除数据时:
ContentProvider就讲到这里,相信大家对ContentProvider非常熟悉了、、、、、、、
1.创建一个ContentProvider的实现类:
新建一个类并继承ContentProvider的类,四大组件都是如此做的,ContentProvider是一个抽象类, 有六个抽象方法 onCreate、getType、delete、update、insert和query,并从写这六个方法
看到delete、update、insert和query这些方法,刚好对应着数据的增删改查四个方法,这些用于供外部应用往ContentProvider增删改查数据,其实的确如此。onCreate方法,该方法在ContentProvider创建后就会被调用,Android开机后,ContentProvider在其它应用第一次访问它时才会被创建,getType方法,该方法用于返回当前Url所代表数据的MIME类型
getType方法
1)如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头,
例如:要得到所有person记录的Uri为content://com.app.wurui.providerdemo.myprovider/person,那么返回的MIME类型字符串应该为:”vnd.android.cursor.dir/person”。
2)如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头,
例如:得到id为10的person记录,Uri为content://com.app.wurui.providerdemo.myprovider/person/10,那么返回的MIME类型字符串为:”vnd.android.cursor.item/person”
2.注册
也是在<\application>节点下进行注册
3.外部访问地址
1)、每一个ContentProvider都拥有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据
2)、Android所提供的ContentProvider都存放在android.provider包中。 将其分为A,B,C,D 4个部分,也可以使用三部分,去掉D部分:
A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;”content://”
B:URI 的标识,用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。这个标识在 元素的 authorities属性中说明:一般是定义该ContentProvider的包.类的名称
C:路径(path),通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就可以了; “content://com.app.wurui.providerdemo.myprovider/person/1”
D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部; “content://com.app.wurui.providerdemo.myprovider/person/tablename/#” #表示数据id
4.UriMatcher类和ContentUris类介绍
在应用ContentProvider之前,先了解俩个类,是android系统专门为ContentProvider提供解析Uri的工具类
1).UriMatcher类
该类提供了两个方法,addURI 和match方法,主要用于匹配Uri
2).ContentUris类
该类提供了三个静态方法,withAppendedId、parseId和appendId方法
上面几个方法,注释写的很清楚,在此不在解释了
5.ContentProvider的简单实例 这里用数据库来存储数据
此处不介绍数据库
public class DBHelper extends SQLiteOpenHelper { public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); } public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) { super(context, name, factory, version, errorHandler); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table person(_id integer primary key autoincrement, name varchar)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
public class MyProvider extends ContentProvider { private DBHelper mDBHelper; private static UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { mUriMatcher.addURI("com.app.wurui.providerdemo.myprovider", "person", 1); mUriMatcher.addURI("com.app.wurui.providerdemo.myprovider", "person/#", 2); } @Override public boolean onCreate() { mDBHelper = new DBHelper(getContext(), "wurui.db", null, 1); return false; } @Nullable @Override//此方法如果正常返回不能关闭数据库连接,projection查询的条目, selection 条件 selectionArgs 条件的参数 sortOrder 排序 public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { SQLiteDatabase database = mDBHelper.getReadableDatabase(); long code = mUriMatcher.match(uri); Cursor cursor = null; if(code == 1){ cursor = database.query("person", projection, selection, selectionArgs, null, null, sortOrder); } else if(code == 2){ long id = ContentUris.parseId(uri); cursor = database.query("person", null, new String("_id = ?"), new String[]{String.valueOf(id)}, null, null, null); } else { database.close(); new RuntimeException("Uri不合法"); } return cursor; } @Nullable @Override public String getType(@NonNull Uri uri) { return null; } @Nullable @Override //values 添加的数据 返回的是添加进去的Uri public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { SQLiteDatabase database = mDBHelper.getReadableDatabase(); long code = mUriMatcher.match(uri); Uri result = null; if(code == 1){ long id = database.insert("person", null, values); result = ContentUris.withAppendedId(uri, id); } else { database.close(); new RuntimeException("Uri不合法"); } database.close(); return result; } @Override//返回值是删除了多少条数据 public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { SQLiteDatabase database = mDBHelper.getReadableDatabase(); long code = mUriMatcher.match(uri); int deleteCount = 0; if(code == 1){ deleteCount = database.delete("person", selection, selectionArgs); } else if(code == 2){ long id = ContentUris.parseId(uri); deleteCount = database.delete("person", "_id = ?", new String[]{String.valueOf(id)}); } else { database.close(); new RuntimeException("Uri不合法"); } database.close(); return deleteCount; } @Override//返回值是更新了多少条数据 public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { SQLiteDatabase database = mDBHelper.getReadableDatabase(); long code = mUriMatcher.match(uri); int updateCount = 0; if(code == 1){ updateCount = database.update("person", values, selection, selectionArgs); } else if(code == 2){ long id = ContentUris.parseId(uri); updateCount = database.update("person", values, "_id = ?", new String[]{String.valueOf(id)}); } else { database.close(); new RuntimeException("Uri不合法"); } database.close(); return updateCount; } }
ContentProvider就写好了,为了验证是否正确,在另一个app调用
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/insert" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="insert"/> <Button android:id="@+id/query" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="query"/> <Button android:id="@+id/update" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="update"/> <Button android:id="@+id/delete" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="delete"/> </LinearLayout>
public class MainActivity extends AppCompatActivity { private int i = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MyOnClickListener listener = new MyOnClickListener(); findViewById(R.id.insert).setOnClickListener(listener); findViewById(R.id.delete).setOnClickListener(listener); findViewById(R.id.query).setOnClickListener(listener); findViewById(R.id.update).setOnClickListener(listener); } class MyOnClickListener implements View.OnClickListener{ @Override public void onClick(View v) { switch (v.getId()){ case R.id.insert: insert(); break; case R.id.delete: delete(); break; case R.id.update: upData(); break; case R.id.query: query(); break; } } } private void upData() { ContentResolver resolver = getContentResolver(); ContentValues values = new ContentValues(); values.put("name", "345"); int count = resolver.update(Uri.parse("content://com.app.wurui.providerdemo.myprovider/person"), values, null, null); System.out.println("更新了" + count + "条----------------------------------------"); } private void delete() { ContentResolver resolver = getContentResolver(); int count = resolver.delete(Uri.parse("content://com.app.wurui.providerdemo.myprovider/person"), "_id = ?", new String[]{String.valueOf(i)}); System.out.println("删除了" + count + "条----------------------------------------"); --i; } private void insert() { ContentResolver resolver = getContentResolver(); ContentValues valus = new ContentValues(); valus.put("name", "wurui" + i); Uri uri = resolver.insert(Uri.parse("content://com.app.wurui.providerdemo.myprovider/person"), valus); ++i; Cursor cursor = resolver.query(uri, null, null, null, null); if(cursor != null){ if(cursor.moveToNext()){ String name = cursor.getString(cursor.getColumnIndex("name")); int id = cursor.getInt(cursor.getColumnIndex("_id")); System.out.println("新增的数据 _id = " + id + " name = " + name + "----------------------------------------"); } } } private void query() { ContentResolver resolver = getContentResolver(); Uri uri = Uri.parse("content://com.app.wurui.providerdemo.myprovider/person"); Cursor cursor = resolver.query(uri, null, null, null, null); if(cursor != null){ while (cursor.moveToNext()){ int id = cursor.getInt(0); String name = cursor.getString(1); System.out.println("id = " + id + " name = " + name); } cursor.close(); } } }
以上就简单实现了ContentProvider的实例
6.监听ContentProvider中数据的变化
1.继承ContentObserver类,并重写onChange方法
public class MyObserver extends ContentObserver { /** * Creates a content observer. * * @param handler The handler to run {@link #onChange} on, or null if none. */ public MyObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); System.out.println("改变了"); } }
2.1注册对指定Uri的监听函数,一旦该Uri指向的内容发生改变,将通知到MyObserver类的onChange方法
getContentResolver().registerContentObserver(Uri.parse("content://com.app.wurui.providerdemo.myprovider/person"), true, mMyObserver);
2.2当程序退出或者不需要再监听Uri的变化时,要主动取消对Uri的监听
if(mMyObserver != null){ getContentResolver().unregisterContentObserver(mMyObserver); mMyObserver = null; }
3.在ContentProvider里,每当特定Uri上的数据发生变化,要触发对调用者对通知。通知使用ContentResolver的notifyChange()方法触发。比如删除数据时:
@Override//返回值是删除了多少条数据 public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { SQLiteDatabase database = mDBHelper.getReadableDatabase(); long code = mUriMatcher.match(uri); int deleteCount = 0; if(code == 1){ deleteCount = database.delete("person", selection, selectionArgs); } else if(code == 2){ long id = ContentUris.parseId(uri); deleteCount = database.delete("person", "_id = ?", new String[]{String.valueOf(id)}); } else { database.close(); new RuntimeException("Uri不合法"); } //当删除数据成功时,就会触发 getContext().getContentResolver().notifyChange(uri, null); database.close(); return deleteCount; }
ContentProvider就讲到这里,相信大家对ContentProvider非常熟悉了、、、、、、、
相关文章推荐
- android四大组件之ContentProvider
- Android的四大组件之ContentProvider总结
- Android 四大组件之一 ContentProvider
- 【Android基础】(4)四大核心组件之ContentProvider
- android开发步步为营之34:四大组件之ContentProvider
- Android 四大组件(Activity、Service、BroadCastReceiver、ContentProvider)
- android四大组件之contentprovider
- 【Android开发日记】之入门篇(九)——Android四大组件之ContentProvider
- Android四大组件之ContentProvider
- android四大组件之ContentProvider
- Android四大组件之ContentProvider自定义
- Android四大组件之一之内容提供者ContentProvider
- Android四大组件之ContentProvider(二)读取设备上的图片、音频和视频
- Android学习日志13__四大组件04__ContentProvider
- Android四大组件之ContentProvider
- 【Android基础入门〖6〗】四大组件之ContentProvider
- Android四大组件之ContentProvider
- Android四大组件之ContentProvider
- Android四大组件之ContentProvider
- Android的四大组件之ContentProvider总结