文章目录
前言:
-
Android四大组件之一,称为内容提供者。有时候需要在应用程序之间共享数据,这时内容提供者变得非常有用。
-
ContenProvider需要在AndroidManifest.xml中注册,一旦提供CP,不论应用启动与否,都可被操作
-
Content Provider以Uri的形式对外提供数据,并且是单例模式
数据共享
- 当作为数据提供方,则需要提供ContentProvider
- 当作为数据接收方,则通过ContectResolver来操作
创建ContentProvider
- 继承类ContentProvider
- 定义访问内容的Uri
- 准备数据
- 在AndroidManifest.xml中注册
Uri讲解
COntentResolver通过uri(统一资源定位符)来定位自己要访问的数据
Uri举例:content://org.edu.provider/words
- content://这部分是Android固定的
- org.edu.provider 这部分是ContentProvider中的authority
- words 资源部份
Uri提供静态方法parse()来实现将字符串给转换为Uri
Uri uri = Uri.parse("content://org.edu.provider/words");
操作Uri的工具类
-
UriMatcher
-
// 构造方法,UrMatcher.NO_MATCH表示不匹配任何路径的返回码 UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); // 用于注册两个Uri match.addURI("org.providers.prods", "words", 1); match.addURI("org.providers.prods", "words/#", 2); //返回1 matcher.match(Uri.parse("content://org.providers.prods/words"); //返回2 matcher.match(Uri.parse("content://org.providers.prods/word/5");
-
-
ContentUris工具类
-
with Append Id(uri,id):为路径uri加上id部分
-
parseId(uri):从指定Uri解析出所包含的Id值
-
Uri uri = Uri.parse("content://org.providers.prods/word"); Uri resultUri = ContentUris.withAppendedId(uri,5); //返回5 Long id = ContentUris.parseId(resultUri);
-
ContentResolver简介
- 获取ContentResolver
context.getContentResolver
- 通过ContentResolver操作数据
insert(uri,values);
delete(uri,where,selectionargs);
update(uri,values,where,selectionargs);
/**
*uri:ContentProvider的Uri
*projection:要返回的内容(列)
*/
query(uri,projection,selection,selectionargs,order);
系统中的ContentProvider
Android系统中会给应用提供一些开放的数据,采用CP的形式
- 通过ContentResolver访问系统CP的步骤:
- 调用Activity中的ContentResolver获取CR对象
- 调用CR中的query等方法获取数据
- ContentProvider访问通话记录
- 通话记录的Uri:CallLog.Calls.CONTENT_URI
public class MainActivity extends AppCompatActivity {
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
visitCP();
}
@SuppressLint("Range")
private void visitCP() {
Cursor cur = getContentResolver().query(
CallLog.Calls.CONTENT_URI, null, null, null, null);
if(cur != null && cur.moveToFirst()) {
do{
String str = cur.getString(cur.getColumnIndex(
CallLog.Calls.NUMBER));
Log.e("Name", str);
}while (cur.moveToNext());
}else {
Log.i("TAG","空值");
}
}
}
自定义的ContentProvider
-
创建ContentProvider
/** * 自定义ContentProvider * 继承ContentProvider类,实现该类的方法 */ public class StudentProvider extends ContentProvider { @Override public boolean onCreate() { return false; } @Nullable @Override public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { return null; } @Nullable @Override public String getType(@NonNull Uri uri) { return null; } @Nullable @Override public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { return null; } @Override public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; } @Override public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; } }
-
配置ContentProvider
<provider android:authorities="com.tanghua.contentprovider.demo1.StudentProvider" android:name=".demo1.StudentProvider" android:exported="true"/>
- authorities:指定CP对应的Uri,相当于分配了一个域名
- name:CP的实现类的类名
- exported:是否允许CP被其他应用调用
-
使用ContentReslover调用方法
Uri uri = Uri.parse("content://com.tanghua.contentprovider.demo1.StudentProvider"); findViewById(R.id.btn_insert).setOnClickListener(view -> { ContentResolver resolver = getContentResolver(); ContentValues values = new ContentValues(); values.put("name","李四"); resolver.insert(uri,values); });CP工具类
CP工具类
为了确定ContentProvider匹配的Uri,使用Urimatcher工具类
void add URI(authority, path, code);
int match(uri)
为了操作Uri,Android使用ContentUris工具类
withAppendedId(uri,id)
parseId(uri)
监听Contentprovider的数据
-
通过ContentObserver进行CP数据修改的监听
-
自定义类继承ContentObserver类,重写onChange方法
-
通过ContentReslover想Uri注册ContentObserver监听器
/** *uri:该监听器所监听的CP的uri *notifyForDescendents:布尔类型,子Uri数据改变时是否出发 *observer:监听器实例 */ registerContentObserver(uri,notifyForDescendents,observer)
-