Android(安卓)ContentProvider学习
ContentProvider介绍:
Android ContentProvider是数据对外的接口,我们只需通过使用ContentProvider访问数据而不需要关心数据具体的存储及访问过程,这样既提高了数据的访问效率,同时也保护了数据。Activity类中有一个继承自ContentWapper的getContentResolver()无参数方法,该方法返回一个ContentResolver对象,通过调用其query、insert、update、delete方法访问数据。这几个方法的第一个参数均为URI型,用来标识资源。
总结:
1、ContentProvider为存储和读取数据提供了统一的接口
2、使用ContentProvider,应用程序可以实现数据共享
3、android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等)
Uri介绍:
1、每一个ContentProvider都拥有一个公共的Uri,这个Uri用于表示这个ContentProvider提供的数据
2、Android所提供的ContentProvider都存放在andriod.provider这个包里面
Android的ContentProviderURI有固定的形式:content://contract/people
前缀:固定为content: //
认证:contract资源的唯一标识符
路径:people具体的资源类型
在Android中广泛应用URI,而不是URL。URL标识资源的物理位置,相当于文件的路径;而URI则是标识资源的逻辑位置,并不提供资源的具体位置。比如说电话薄中的数据,如果用URL来标识的话,可能会是一个很复杂的文件结构,而且一旦文件的存储路径改变,URL也必须得改动。但是若是URI,则可以用诸如content://contract/people这样容易记录的逻辑地址来标识,而且并不需要关心文件的具体位置,即使文件位置改动也不需要做变化,当然这都是对于用户来说,后台程序中URI到具体位置的映射还是需要程序员来改动的。
ContentProvider提供的函数:
1、query()查询
2、insert()插入
3、update()更新
4、delete() 删除
5、getType()得到数据类型
6、onCreate()创建时的回调函数
实现ContentProvider的过程:
1、定义一个COTENT_URI常量
2、定义一个类,继承ContentProvider
3、实现query(),delete(),update(),insert(),onCreate(),getType()方法
4、在AndroidMainfest.xml中申明
下面以两个实例(一个是ContentProvider所在的应用,另一个是使用ContentProvider的应用),说明如何使用ContentProvider
ContentProvider所在的应用
1、定义一个类,里面定义一些常量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package com.yyl.android; import android.net.Uri; import android.provider.BaseColumns; public class MyUsers { public static final String AUTHORITY = "com.yyl.android.MyContentProvider"; // BaseColumn类中已经包含了_id字段 public static final class User implements BaseColumns { // 定义Uri public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY); // 定义数据表列 public static final String USER_NAME = "USER_NAME"; } } |
2、定义一个继承ContentProvider的子类,实现其方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | package com.yyl.android; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; /** * MyContentProvider继承ContentProvider类,实现其insert,update,delete,getType,onCreate等方法 */ public class MyContentProvider extends ContentProvider { // 定义一个SQLiteDatabase变量 private SQLiteDatabase sqlDB; // 定义一个DatabaseHelper变量 private DatabaseHelper dbHelper; // 数据库名 private static final String DATABASE_NAME = "Users.db"; // 数据库版本 private static final int DATABASE_VERSION = 1; // 表名 private static final String TABLE_NAME = "User"; // 标签 private static final String TAG = "MyContentProvider"; /** * 定义一个内部类 * * 这个内部类继承SQLiteOpenHelper类,重写其方法 */ public static class DatabaseHelper extends SQLiteOpenHelper { // 构造方法 public DatabaseHelper(Context context) { // 父类构造方法 super(context, DATABASE_NAME, null, DATABASE_VERSION); } // 当第一次创建数据库的时候调用该方法,可以为数据库增加一些表,和初始化一些数据 @Override public void onCreate(SQLiteDatabase db) { // 在数据库里生成一张表 db.execSQL("Create table " + TABLE_NAME + "( _id INTEGER PRIMARY KEY AUTOINCREMENT, USER_NAME TEXT);"); } // 当更新数据库版本的时候,调用该方法。可以删除,修改表的一些信息 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); } } // 这是一个回调函数,当生成所在类的对象时,这个方法被调用,创建一个数据库 @Override public boolean onCreate() { dbHelper = new DatabaseHelper(getContext()); return (dbHelper == null) ? false : true; } // 查询 @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); SQLiteDatabase db = dbHelper.getReadableDatabase(); qb.setTables(TABLE_NAME); Cursor c = qb.query(db, projection, selection, null, null, null, sortOrder); c.setNotificationUri(getContext().getContentResolver(), uri); return c; } // 取得类型 @Override public String getType(Uri uri) { return null; } // 插入数据 @Override public Uri insert(Uri uri, ContentValues contentvalues) { sqlDB = dbHelper.getWritableDatabase(); long rowId = sqlDB.insert(TABLE_NAME, "", contentvalues); if (rowId > 0) { Uri rowUri = ContentUris.appendId( MyUsers.User.CONTENT_URI.buildUpon(), rowId).build(); getContext().getContentResolver().notifyChange(rowUri, null); return rowUri; } throw new SQLException("Failed to insert row into" + uri); } // 删除数据 @Override public int delete(Uri uri, String selection, String[] selectionArgs) { return 0; } // 更新数据 @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; } } |
3、定义一个默认加载的Activity,里面对ContentProvider进行数据加载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | package com.yyl; import com.yyl.android.MyUsers; import android.app.Activity; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.widget.Toast; public class MyContentDemo extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); insertRecord("MyUser"); insertRecord("YangYuLin"); displayRecords(); } private void insertRecord(String userName) { ContentValues values = new ContentValues(); values.put(MyUsers.User.USER_NAME, userName); getContentResolver().insert(MyUsers.User.CONTENT_URI, values); } private void displayRecords() { String columns[] = new String[] { MyUsers.User._ID, MyUsers.User.USER_NAME }; Uri myUri = MyUsers.User.CONTENT_URI; Cursor cur = managedQuery(myUri, columns, null, null, null); if (cur.moveToFirst()) { String id = null; String userName = null; do { id = cur.getString(cur.getColumnIndex(MyUsers.User._ID)); userName = cur.getString(cur .getColumnIndex(MyUsers.User.USER_NAME)); Toast.makeText(this, id + " " + userName, Toast.LENGTH_LONG) .show(); } while (cur.moveToNext()); } } } |
4、在AndroidMainfest.xml里注册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.yyl" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <provider android:name=".android.MyContentProvider" android:authorities="com.yyl.android.MyContentProvider" /> <activity android:name=".MyContentDemo" 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> <uses-sdk android:minSdkVersion="7" /> </manifest> |
做另一个App.使用上面ContentProvider提供的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | package yyl.client; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.text.Editable; import android.view.View; import android.widget.Button; import android.widget.EditText; public class CPClientActitity extends Activity { public static final String AUTHORITY = "com.yyl.android.MyContentProvider"; private Button insertButton = null; // 访问ContentProvider的Uri Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 得到ContentProvider对于表的所有数据,以游标格式保存 Cursor c = managedQuery(CONTENT_URI, new String[] { "_id", "USER_NAME" }, null, null, null); // 循环打印ContentProvider的数据 if (c.moveToFirst()) { String _id = null; String user_name = null; do { // 得到_id列,USER_NAME列 _id = c.getString(c.getColumnIndex("_id")); user_name = c.getString(c.getColumnIndex("USER_NAME")); System.out.println("_id = " + _id + ", user_name = " + user_name); } while (c.moveToNext()); } // 根据Id得到控件对象 insertButton = (Button) findViewById(R.id.Insert); // 给按钮绑定事件监听器 insertButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 得到EditText输入的数据 String username = ((EditText) findViewById(R.id.userName)) .getText().toString(); // 生成一个ContentResolver对象 ContentResolver cr = getContentResolver(); // 生成一个ContentValues对象 ContentValues values = new ContentValues(); // 将EditText输入的值,保存到ContentValues对象中 values.put("USER_NAME", username); // 插入数据 cr.insert(CONTENT_URI, values); } }); } } |
更多相关文章
- SpringBoot 2.0 中 HikariCP 数据库连接池原理解析
- 一句话锁定MySQL数据占用元凶
- Android(安卓)sqlite3 详解
- android关闭其他app
- 数据存储之Shared Preferences
- 在Android(安卓)Jar包使用图片资源的解决方法
- Android(安卓)ListView缓存惹得祸
- 64位系统中安装Android(安卓)SDK“系统找不到指定的文件Java.exe
- Android第一行代码第二版:5.3.2发送有序广播,在安卓8上无法接收广