Android中ContentProvider的理解使用
来源:互联网 发布:马云 英文演讲 知乎 编辑:程序博客网 时间:2024/06/12 20:42
前言
Android四大组件对大家来说都不陌生,但是相对于Activity,Service,广播来说,ContentProvider好像很容易被忽略,因为他确实在普通项目中很少使用,不使用它也能很好的完成项目需求,但是ContentProvider我觉得是Android中最牛逼的设计之一了,很多的数据共享都是用它来实现的,最常用的是android获取手机联系人就是用的ContentProvider来实现的.
ContentProvider介绍
以下内容摘自谷歌:
Content providers are one of the primary building blocks of Android applications, providing content to applications. They encapsulate data and provide it to applications through the single ContentResolver interface. A content provider is only required if you need to share data between multiple applications. For example, the contacts data is used by multiple applications and must be stored in a content provider. If you don't need to share data amongst multiple applications you can use a database directly via SQLiteDatabase.
谷歌翻译:
内容提供者是Android应用程序的主要组成部分之一,为应用程序提供内容。 它们封装数据,并通过单个ContentResolver接口将其提供给应用程序。 只有在需要在多个应用程序之间共享数据时,才需要内容提供者。 例如,联系人数据由多个应用程序使用,并且必须存储在内容提供者中。 如果您不需要在多个应用程序之间共享数据,则可以直接通过SQLiteDatabase使用数据库。
白话翻译:
ContentProvider用来实现不同App间的数据共享,就好比手机联系人,它本身的实现方式就使用了ContentProvider,它本身属于“内容的提供者”,它实现机制就是为了数据共享.因此,手机联系人是内容提供者,是数据的来源,其他第三方的数据需要使用它的数据,可以通过ContentResolver接口(数据通道)共享给其他应用程序.谷歌还说了,如果不需要共享数据,那就直接使用SQLite数据库吧.
ContentProvider"内容提供者"实现步骤
ContentProvider组成部分
ContentProvider主要通过Uri(统一资源定位符)来向外共享数据的.
Uri由三部分组成(Uri可以类比于http://www.baidu.com,相对于绝对地址,就是数据存储的位置)
1.scheme
ContentProvider(内容提供者)的scheme已经由Android所规定.
scheme为:content://
2.主机名
主机名(或叫Authority)用于唯一标识这个ContentProvider,比如这里 com.contentproviderdb.TestContentProvider,外部调用者可以 根据这个标识来找到它。
3.path
路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,今天demo我新建的User表
/User
上面三个部分是主要的,还可以有更详细的,比如还包含数据id /User/id。
上面三个部分是主要的,还可以有更详细的,比如还包含数据id /User/id。
如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
Uri uri = Uri.parse("content://com.contentproviderdb.TestContentProvider/User").
然后再介绍一下UriMatcher类使用:
因为Uri代表了要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri 的工具类,分别为UriMatcher和ContentUris 。掌握它们的使用,会便于我们的开发工作。
UriMatcher类用于匹配Uri,它的用法如下:
然后再介绍一下UriMatcher类使用:
因为Uri代表了要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri 的工具类,分别为UriMatcher和ContentUris 。掌握它们的使用,会便于我们的开发工作。
UriMatcher类用于匹配Uri,它的用法如下:
if(uriMatcher.match(uri) == USER)
首先第一步把你需要匹配Uri路径全部给注册上,如下:
uriMatcher.addURI("com.contentproviderdb.TestContentProviderr","User",USER);
注册完需要匹配的Uri后,就可以使用sMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配 码是调用addURI()方法传入的第三个参数。
还有ContentUris
ContentUris类用于操作Uri路径后面的ID部分,它有个比较实用的方法:
withAppendedId(uri, id)用于为路径加上ID部分:
u = ContentUris.withAppendedId(uri,d);
withAppendedId(uri, id)用于为路径加上ID部分:
u = ContentUris.withAppendedId(uri,d);
后续会有代码展示.
ContentProvider使用步骤
跟Activity,Service一样,需要在Android配置文件中配置.
在Application节点内注册TestContentProvider:
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".LoginActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".UserListActivity" android:configChanges="orientation|keyboardHidden" android:screenOrientation="portrait" /> <provider android:name=".TestContentProvider" android:authorities="com.contentproviderdb.TestContentProvider" android:process="com.contentproviderdb.TestContentProvider" android:exported="true" /> </application>
小彩蛋:
android:authorities:最好带上包名写上全部路径名称.
android:process:意思是该provider单独运行于一个进程中,防止获取不到内容提供者数据时,可以尝试加上该属性.
android:exported 为true:该属性默认不加的时候,就是该Provider可以共享数据,可以让其他应用程序使用它的数据,反之,则其他应用程序不能使用它的数据。
ContentProvider Java代码实现
继承ContentProvider,建立TestContentProvider类,里面为CRUD操作(增删改查),和数据库操作一样.其他应用程序操作数据时,就是调用的这个类,大家可以断点调试下.
package com.contentproviderdb;import android.content.ContentProvider;import android.content.ContentUris;import android.content.ContentValues;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.net.Uri;import android.support.annotation.NonNull;import android.support.annotation.Nullable;/** * Created by sdj on 2017/9/7. */public class TestContentProvider extends ContentProvider { DBHelper dbHelper; @Override public boolean onCreate() { dbHelper = new DBHelper(getContext()); return false; } @Nullable @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = dbHelper.getReadableDatabase(); Cursor c = db.query("user", null, selection, selectionArgs, null, null, null); return c; } @Nullable @Override public String getType(@NonNull Uri uri) { return null; } @Nullable @Override public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) { SQLiteDatabase db = dbHelper.getWritableDatabase(); long id = db.insert("user", null, contentValues); getContext().getContentResolver().notifyChange(uri, null); return ContentUris.withAppendedId(uri, id); } @Override public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) { return 0; } @Override public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) { return 0; }}
ContentProvider在自身应用程序中实现数据的插入,展示
向User表插入数据
private void insertUser() { Uri uri = Uri.parse("content://com.contentproviderdb.TestContentProvider"); ContentValues contentValues = new ContentValues(); contentValues.put("userName", mEmailView.getText().toString()); contentValues.put("userPwd", mPasswordView.getText().toString()); getContentResolver().insert(uri, contentValues); }
查询插入的数据
URIS还是上面插入的那个地址,我使用TextView简单展示
Uri uri = Uri.parse(URIS); Cursor cursor = getContentResolver().query(uri, null, null, null, null); if (null != cursor && cursor.getCount() > 0) { StringBuilder stringBuilder = new StringBuilder("用户列表如下:\n"); while (cursor.moveToNext()) { stringBuilder.append(cursor.getString(cursor.getColumnIndex("userName")) + " 密码= " + cursor.getString(cursor.getColumnIndex("userPwd")) + "\n"); } user.setUserName(stringBuilder.toString()); }
插入效果图:
展示效果图:
使用其他应用程序操作内容提供者数据
这里我使用我其他的一个项目,在其登录成功后,向TestContentProvider插入一条数据。
private Handler handler=new Handler(){@Overridepublic void handleMessage(Message msg) {if(MyApplication.session==null){dialog.dismiss();Toast.makeText(LoginActivity.this, "账号或密码错误", Toast.LENGTH_SHORT).show();}else{dialog.dismiss();Intent intent=new Intent(LoginActivity.this, HomeActivity.class);startActivity(intent);finish();//Toast.makeText(LoginActivity.this, "登入成功", Toast.LENGTH_SHORT).show();Uri uri = Uri.parse("content://com.contentproviderdb.TestContentProvider");ContentValues contentValues = new ContentValues();contentValues.put("userName","1120184385@qq.com");contentValues.put("userPwd","qazwsx");getContentResolver().insert(uri,contentValues);}super.handleMessage(msg);}};
登录后打开内容提供者查看数据:
可以看到最后一天咱们是通过其他应用程序插入的.
最后,我们可以想下,如果内容提供者不再了,第三方程序再执行操作会怎么样
答案是肯定的,肯定会出错,下面是出错log
Failed to find provider info for com.contentproviderdb.TestContentProvider09-07 06:25:57.527 13948-13948/? E/AndroidRuntime: FATAL EXCEPTION: main java.lang.IllegalArgumentException: Unknown URL content://com.contentproviderdb.TestContentProvider at android.content.ContentResolver.insert(ContentResolver.java:860) at com.email.LoginActivity$1.handleMessage(LoginActivity.java:53) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4745) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) at dalvik.system.NativeStart.main(Native Method)
你想,内容提供者都不在了,你怎么去操作它本身的数据,因此,大家在使用时,多注意下.
这样,对于一些恶心的全家桶软件就很容易理解了,大多数是要数据共享的,比如淘宝作为内容提供者,咸鱼可以使用淘宝数据,天猫也可以使用淘宝数据等,其实也是最基本的一些操作吧,根据自身业务连身定做吧!
阅读全文
1 0
- Android中ContentProvider的理解使用
- Android中ContentProvider的使用
- Android中使用ContentProvider的必要性
- 关于android中自定义contentprovider的使用
- Android中内容提供者ContentProvider的使用
- Android中ContentProvider的简单使用
- Android中关于ContentProvider类的getType()方法的理解
- ContentProvider的理解与使用
- ContentProvider的理解和使用
- ContentProvider的理解与使用
- android ContentProvider中getType(Uri uri)的理解
- android ContentProvider中getType(Uri uri)的理解
- android ContentProvider中getType(Uri uri)的理解
- Android ContentProvider的使用
- 【Android】ContentProvider的使用
- Android ContentProvider的使用
- android ContentProvider的使用
- android ContentProvider的使用
- django UnicodeDecodeError
- 改造自己的ubuntu主题为Mac OS
- 文章标题
- 使用Android Studio引入开源library出现Gradle sync failed: No service of type Factory<LoggingManagerInternal>
- MySQL5.7密码安全策略
- Android中ContentProvider的理解使用
- 在FPGA上实现H.264/AVC视频编码标准
- Android Studio 小技巧/快捷键 合集
- MongoDB 条件操作符说明
- springboot war包导出
- Comment.js模块暴露方法(exports、module.exports)的区别
- 第一天打卡,linux学习
- Android Studio使用gradle打包jar文件脚本:
- String.split