android四大组件--ContentProvider详解

时间:2022-12-21 12:37:34

一、相关ContentProvider概念解析:

    1、ContentProvider简介
在Android官方指出的Android的数据存储方式总共有五种,分别是:Shared Preferences、网络存储、文件存储、外储存储、SQLite。但是我们知道一般这些存储都只是在单独的一个应用程序之中达到一个数据的共享,有时候我们需要操作其他应用程序的一些数据,例如我们需要操作系统里的媒体库、通讯录等,这时我们就可能通过ContentProvider来满足我们的需求了。

2、为什么要选择ContentProvider?

ContentProvider向我们提供了我们在应用程序之间共享数据的一种机制,而我们知道每一个应用程序都是运行在不同的进程的?,数据和文件在不同应用程序之间达到数据的共享不是没有可能,而是显得比较复杂,而正好Android中的ContentProvider则达到了这一需求,比如有时候我们需要操作手机里的联系人,手机里的多媒体等一些信息,我们都可以用到这个ContentProvider来达到我们所需。

1)ContentProvider为存储和获取数据提供了统一的接口。ContentProvide对数据进行封装,不用关心数据存储的细节。使用表的形式来组织数据。
2)使用ContentProvider可以在不同的应用程序之间共享数据。 
3)Android为常见的一些数据提供了默认的ContentProvider(包括音频、视频、图片和通讯录等)。 

总的来说使用ContentProvider对外共享数据的好处是统一了数据的访问方式。

    

ContentProvider什么时候创建

启动App,Provider创建

10-08 14:20:06.794    7067-7067/com.silion.sampleprovider V/slong.liang﹕ MainProvider onCreate
    10-08 14:20:06.814    7067-7067/com.silion.sampleprovider V/slong.liang﹕ MainDatabaseHelper : onCreate

    3、Uri介绍
为系统的每一个资源给其一个名字,比方说通话记录。
1)、每一个ContentProvider都拥有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据。 
2)、Android所提供的ContentProvider都存放在android.provider包中。 将其分为A,B,C,D 4个部分:

android四大组件--ContentProvider详解

android四大组件--ContentProvider详解

A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;"content://"
B:URI 的标识,用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。这个标识在 元素的 authorities属性中说明:一般是定义该ContentProvider的包.类的名称
C:路径(path),通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就可以了;"content://com.silion.providersample/tablename"
D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部; "content://com.silion.providersample/tablename/#" #表示数据id。

PS:
路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
1) 要操作person表中id为10的记录,可以构建这样的路径:/person/10
2) 要操作person表中id为10的记录的name字段, person/10/name
3) 要操作person表中的所有记录,可以构建这样的路径:/person
4) 要操作xxx表中的记录,可以构建这样的路径:/xxx
5) 当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式,如下:
要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name
6) 果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:Uri uri = Uri.parse("content://com.silion.providersample/tablename")


1. 常量 MainContract.java 实现  BaseColumns

package com.silion.sampleprovider;

import android.net.Uri;
import android.provider.BaseColumns;

/**
* Created by silion on 2015/10/5.
*/
public class MainContract implements BaseColumns {
public interface Tables {
public static final String USER = "user";
}

public interface User {
public static final Uri USER_URI = Uri.parse("content://com.silion.sampleprovider/user");
public static final String SORT_OERDER = "_ID ASC";
public static final String NAME = "name";
public static final String AGE = "age";
public static final String PHONE = "phone";
public static final String DIR = "vnd.android.cusor.dir/vnd.com.silion.provider.user";
public static final String ITEM = "vnd.android.cusor.item/vnd.com.silion.provider.user";
}
}

2.. SQLite操作类:MainDatabaseHelper.java 继承于 SQLiteOpenHelper

package com.silion.sampleprovider;

import android.content.Context;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import com.silion.sampleprovider.MainContract.User;
import com.silion.sampleprovider.MainContract.Tables;

/**
* Created by silion on 2015/10/5.
*/
public class MainDatabaseHelper extends SQLiteOpenHelper {

public MainDatabaseHelper(Context context, String name) {
this(context, name, 1);
}

public MainDatabaseHelper(Context context, String name, int version) {
this(context, name, null, version);
}
public MainDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}

@Override
public void onCreate(SQLiteDatabase db) {
android.util.Log.v("slong.liang", "MainDatabaseHelper : onCreate");
db.execSQL("CREATE TABLE " + Tables.USER + "(" +
MainContract._ID + " INTEGER PRIMARY KEY," +
User.NAME + " TEXT," +
User.AGE + " INTEGER," +
User.PHONE + " TEXT" + ")");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
android.util.Log.v("slong.liang", "MainDatabaseHelper : onUpgrade oldVersion = " +
oldVersion + ", newVersion = " + newVersion);
db.execSQL("DROP TABLE IF EXISTS " + Tables.USER);
onCreate(db);
}
}


3. MainProvider.java 继承于 ContentProvider

package com.silion.sampleprovider;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;

import com.silion.sampleprovider.MainContract.User;
import com.silion.sampleprovider.MainContract.Tables;

/**
* Created by silion on 2015/10/5.
*/
public class MainProvider extends ContentProvider {
private static final String AUTHORITY = "com.silion.sampleprovider";
private static final String DB_NAME = "sample";

private static final int USER = 1;
private static final int USER_ID = 2;
private MainDatabaseHelper mDatabaseHelper = null;

public static final UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
mUriMatcher.addURI(AUTHORITY, Tables.USER, USER);
mUriMatcher.addURI(AUTHORITY, Tables.USER + "/#", USER_ID);
}

@Override
public boolean onCreate() {
mDatabaseHelper = new MainDatabaseHelper(getContext(), DB_NAME);
mDatabaseHelper.getReadableDatabase();
return true;
}

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = mDatabaseHelper.getReadableDatabase();
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
int match = mUriMatcher.match(uri);
switch (match) {
case USER: {
qb.setTables(Tables.USER);
//qb.setProjectionMap(null); 不使用看有没有问题
if(TextUtils.isEmpty(sortOrder)) {
sortOrder = MainContract.SORT_OERDER;
}
break;
}
case USER_ID: {
qb.setTables(Tables.USER);
//qb.setProjectionMap(null); 不使用看有没有问题
qb.appendWhere(MainContract._ID + " = " + uri.getLastPathSegment()); //????
break;
}
default: {
break;
}
}
Cursor cursor = qb.query(db, projection, selection, selectionArgs, null , null, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}

@Override
public String getType(Uri uri) {
switch (mUriMatcher.match(uri)) {
case USER:
return User.DIR;
case USER_ID:
return User.ITEM;
default:
throw new IllegalArgumentException("Unknow uri: " + uri);
}
}

@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
long id = -1;
int match = mUriMatcher.match(uri);
switch(match) {
case USER:
id = db.insert(Tables.USER, User.NAME, values);
break;
default:
break;
}
if(id > 0) {
uri = ContentUris.withAppendedId(uri, id);
android.util.Log.v("slong.liang", "SampleProvider.insert uri = " + uri.toString());
getContext().getContentResolver().notifyChange(uri, null);
return uri;
}
return null;
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
int match = mUriMatcher.match(uri);
int count = -1;
switch(match) {
case USER:
count = db.delete(Tables.USER, selection, selectionArgs);
break;
case USER_ID:
String userId = uri.getPathSegments().get(1);
if(selection != null) {
selection = MainContract._ID + " = " + userId + " AND " + selection;
}
count = db.delete(Tables.USER, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknow URI: " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
int match = mUriMatcher.match(uri);
int count = -1;
switch(match) {
case USER:
count = db.update(Tables.USER, values, selection, selectionArgs);
break;
case USER_ID:
String userId = uri.getPathSegments().get(1);
if(selection != null) {
selection = MainContract._ID + " = " + userId + " AND " + selection;
}
count = db.update(Tables.USER, values, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknow URI: " + uri);
}
return count;
}
}

4. 注册

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.silion.sampleprovider">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<provider
android:name=".MainProvider"
android:authorities="com.silion.sampleprovider"></provider>
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

5. 布局activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity">

<Button
android:id="@+id/insert"
android:text="@string/insert"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<Button
android:id="@+id/query"
android:text="@string/query"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<Button
android:id="@+id/update"
android:text="@string/update"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

<Button
android:id="@+id/delete"
android:text="@string/delete"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>


6. MainAcitivty.java

package com.silion.sampleprovider;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.silion.sampleprovider.MainContract.User;

public class MainActivity extends Activity {

View.OnClickListener mClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.insert: {
ContentValues values = new ContentValues();
values.put(User.NAME, "silion");
values.put(User.AGE, 28);
values.put(User.PHONE, "10086");
ContentResolver cr = getContentResolver();
Uri uri = cr.insert(User.URI, values);
android.util.Log.v("slong.liang", "insert uri = " + uri);
break;
}
case R.id.query: {
String[] projection = new String[] {User.NAME, User.AGE, User.PHONE};
String selection = User.NAME + " =? OR " + User.NAME + " =?";
String[] selectionArgs = new String[] {"silion", "xixi"};
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(User.URI, projection, selection, selectionArgs, null);
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex(User.NAME));
int age = cursor.getInt(cursor.getColumnIndex(User.AGE));
String phone = cursor.getString(cursor.getColumnIndex(User.PHONE));
android.util.Log.v("slong.liang", "query name = " + name + ", age = " + age + ", phone = " + phone);
}
break;
}
case R.id.update: {
ContentValues values = new ContentValues();
values.put(User.NAME, "xixi");
values.put(User.PHONE, "10086");
String where = User.NAME + " =?";
String[] selectionArgs = new String[] {"silion"};
ContentResolver cr = getContentResolver();
int id = cr.update(User.URI, values, where, selectionArgs);
Uri uri = ContentUris.withAppendedId(User.URI, id);
android.util.Log.v("slong.liang", "insert uri = " + uri);
break;
}
case R.id.delete: {
String where = User.NAME + " =? OR " + User.NAME + " =?";
String[] selectionArgs = new String[] {"xixi", "silion"};
ContentResolver cr = getContentResolver();
int rowNum = cr.delete(User.URI, where, selectionArgs);
android.util.Log.v("slong.liang", "insert rowNum = " + rowNum);
break;
}
default:
break;
}
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button insertButton = (Button) findViewById(R.id.insert);
insertButton.setOnClickListener(mClickListener);
Button queryButton = (Button) findViewById(R.id.query);
queryButton.setOnClickListener(mClickListener);
Button updateButton = (Button) findViewById(R.id.update);
updateButton.setOnClickListener(mClickListener);
Button deleteButton = (Button) findViewById(R.id.delete);
deleteButton.setOnClickListener(mClickListener);
}

}