带你学习Android中的ContentProvider

打印 上一主题 下一主题

主题 853|帖子 853|积分 2559

Android中的ContentProvider

ContentProvider是Android中用于管理应用数据共享的组件。它允许不同应用之间访问和利用数据,通过定义统一的接口,确保数据的安全性和同等性。ContentProvider通常用于访问SQLite数据库、文件、网络等数据源。


ContentProvider的工作原理

ContentProvider的核心作用是提供一个标准化的接口,使得不同的应用程序能够以同等的方式访问数据。利用ContentProvider时,其他应用通过URI(统一资源标识符)来哀求数据,而且可以实行CRUD(创建、读取、更新、删除)利用。

  • URI:每个ContentProvider都有一个唯一的URI,其他应用通过这个URI来访问数据。
  • 数据利用:ContentProvider提供了四个基本利用:

    • query(): 查询数据
    • insert(): 插入新数据
    • update(): 更新已有数据
    • delete(): 删除数据

  • 权限管理:可以为ContentProvider设置权限,控制哪些应用能够访问数据。

创建一个简单的ContentProvider

以下是一个示例,展示怎样创建和利用ContentProvider来管理应用数据。
1. 定义数据模型

首先定义一个简单的数据模型,例如用户信息:
  1. public class User {
  2.     public static final String TABLE_NAME = "users";
  3.     public static final String COLUMN_ID = "_id";
  4.     public static final String COLUMN_NAME = "name";
  5.     public static final String COLUMN_EMAIL = "email";
  6. }
复制代码
2. 创建SQLiteHelper

利用SQLite来存储数据,并创建一个SQLiteOpenHelper类来管理数据库的创建和版本管理:
  1. public class UserDatabaseHelper extends SQLiteOpenHelper {
  2.     private static final String DATABASE_NAME = "users.db";
  3.     private static final int DATABASE_VERSION = 1;
  4.     public UserDatabaseHelper(Context context) {
  5.         super(context, DATABASE_NAME, null, DATABASE_VERSION);
  6.     }
  7.     @Override
  8.     public void onCreate(SQLiteDatabase db) {
  9.         String CREATE_USERS_TABLE = "CREATE TABLE " + User.TABLE_NAME + " ("
  10.                 + User.COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
  11.                 + User.COLUMN_NAME + " TEXT, "
  12.                 + User.COLUMN_EMAIL + " TEXT)";
  13.         db.execSQL(CREATE_USERS_TABLE);
  14.     }
  15.     @Override
  16.     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  17.         db.execSQL("DROP TABLE IF EXISTS " + User.TABLE_NAME);
  18.         onCreate(db);
  19.     }
  20. }
复制代码
3. 创建ContentProvider

实现一个ContentProvider,并重写必要的方法:
  1. public class UserContentProvider extends ContentProvider {
  2.     private static final String AUTHORITY = "com.example.usersprovider";
  3.     private static final UriMatcher uriMatcher;
  4.     private static final int USERS = 1;
  5.    
  6.     static {
  7.         uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
  8.         uriMatcher.addURI(AUTHORITY, User.TABLE_NAME, USERS);
  9.     }
  10.     private UserDatabaseHelper dbHelper;
  11.     @Override
  12.     public boolean onCreate() {
  13.         dbHelper = new UserDatabaseHelper(getContext());
  14.         return true;
  15.     }
  16.     @Override
  17.     public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
  18.         SQLiteDatabase db = dbHelper.getReadableDatabase();
  19.         Cursor cursor = db.query(User.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
  20.         cursor.setNotificationUri(getContext().getContentResolver(), uri);
  21.         return cursor;
  22.     }
  23.     @Override
  24.     public Uri insert(Uri uri, ContentValues values) {
  25.         SQLiteDatabase db = dbHelper.getWritableDatabase();
  26.         long id = db.insert(User.TABLE_NAME, null, values);
  27.         getContext().getContentResolver().notifyChange(uri, null);
  28.         return ContentUris.withAppendedId(uri, id);
  29.     }
  30.     @Override
  31.     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
  32.         SQLiteDatabase db = dbHelper.getWritableDatabase();
  33.         int count = db.update(User.TABLE_NAME, values, selection, selectionArgs);
  34.         getContext().getContentResolver().notifyChange(uri, null);
  35.         return count;
  36.     }
  37.     @Override
  38.     public int delete(Uri uri, String selection, String[] selectionArgs) {
  39.         SQLiteDatabase db = dbHelper.getWritableDatabase();
  40.         int count = db.delete(User.TABLE_NAME, selection, selectionArgs);
  41.         getContext().getContentResolver().notifyChange(uri, null);
  42.         return count;
  43.     }
  44.     @Override
  45.     public String getType(Uri uri) {
  46.         switch (uriMatcher.match(uri)) {
  47.             case USERS:
  48.                 return "vnd.android.cursor.dir/" + AUTHORITY + "." + User.TABLE_NAME;
  49.             default:
  50.                 throw new UnsupportedOperationException("Unknown URI: " + uri);
  51.         }
  52.     }
  53. }
复制代码
4. 注册ContentProvider

在AndroidManifest.xml中注册ContentProvider:
  1. <provider
  2.     android:name=".UserContentProvider"
  3.     android:authorities="com.example.usersprovider"
  4.     android:exported="true" />
复制代码
利用ContentProvider

其他应用或组件可以通过ContentResolver来访问ContentProvider中的数据,例如
1. 插入新用户数据
  1. ContentValues values = new ContentValues();
  2. values.put(User.COLUMN_NAME, "John Doe");
  3. values.put(User.COLUMN_EMAIL, "john@example.com");
  4. Uri uri = getContentResolver().insert(Uri.parse("content://com.example.usersprovider/users"), values);
复制代码
2. 查询用户数据的示例
  1. Cursor cursor = getContentResolver().query(Uri.parse("content://com.example.usersprovider/users"), null, null, null, null);
  2. if (cursor != null) {
  3.     while (cursor.moveToNext()) {
  4.         String name = cursor.getString(cursor.getColumnIndex(User.COLUMN_NAME));
  5.         String email = cursor.getString(cursor.getColumnIndex(User.COLUMN_EMAIL));
  6.         // 处理数据
  7.     }
  8.     cursor.close();
  9. }
复制代码
3. 监听ContentProvider的变化
在Android中,ContentProvider不仅允许不同应用之间共享数据,还提供了机制来监听数据的变化。通过注册观察者,应用可以接收来自ContentProvider的数据更改通知,从而实现更好的数据同步和用户体验。
3.1 内容观察者的工作原理
Android中的ContentObserver类用于监听ContentProvider的数据变化。每当数据发生变化时,ContentProvider会通知所有注册的观察者。ContentObserver会被触发,允许应用实时更新UI或实行其他必要的利用。其核心步骤为:
1)创建ContentObserver:子类化ContentObserver,实现onChange()方法。
  1. import android.database.ContentObserver;
  2. import android.os.Handler;
  3. import android.util.Log;
  4. public class UserContentObserver extends ContentObserver {
  5.     private static final String TAG = "UserContentObserver";
  6.     public UserContentObserver(Handler handler) {
  7.         super(handler);
  8.     }
  9.     @Override
  10.     public void onChange(boolean selfChange) {
  11.         super.onChange(selfChange);
  12.         // 数据变化时的逻辑
  13.         Log.d(TAG, "Data in ContentProvider has changed!");
  14.         // 可以在这里添加代码,更新UI或执行其他操作
  15.     }
  16. }
复制代码
2)注册ContentObserver:通过ContentResolver注册观察者。
在需要监听数据变化的Activity或Fragment中,注册ContentObserver。通常在onStart()方法中注册,在onStop()方法中取消注册,以克制内存泄漏:
  1. import android.database.ContentObserver;
  2. import android.os.Bundle;
  3. import android.os.Handler;
  4. import androidx.appcompat.app.AppCompatActivity;
  5. public class UserActivity extends AppCompatActivity {
  6.     private UserContentObserver userContentObserver;
  7.     @Override
  8.     protected void onCreate(Bundle savedInstanceState) {
  9.         super.onCreate(savedInstanceState);
  10.         setContentView(R.layout.activity_user);
  11.         
  12.         // 创建Handler用于更新UI
  13.         Handler handler = new Handler();
  14.         userContentObserver = new UserContentObserver(handler);
  15.     }
  16.     @Override
  17.     protected void onStart() {
  18.         super.onStart();
  19.         // 注册ContentObserver
  20.         getContentResolver().registerContentObserver(
  21.             Uri.parse("content://com.example.usersprovider/users"),
  22.             true,  // 监视子URI的变化
  23.             userContentObserver
  24.         );
  25.     }
  26.     @Override
  27.     protected void onStop() {
  28.         super.onStop();
  29.         // 取消注册ContentObserver
  30.         getContentResolver().unregisterContentObserver(userContentObserver);
  31.     }
  32. }
复制代码
3)处理变化:在onChange()方法中处理数据变化的逻辑。
3.2 ContentProvider更新数据并触发通知
在ContentProvider中,每当实行插入、更新或删除利用时,需要调用notifyChange()方法来通知观察者。以下是ContentProvider中的示例:
  1. @Override
  2. public Uri insert(Uri uri, ContentValues values) {
  3.     SQLiteDatabase db = dbHelper.getWritableDatabase();
  4.     long id = db.insert(User.TABLE_NAME, null, values);
  5.     getContext().getContentResolver().notifyChange(uri, null); // 通知观察者
  6.     return ContentUris.withAppendedId(uri, id);
  7. }
  8. @Override
  9. public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
  10.     SQLiteDatabase db = dbHelper.getWritableDatabase();
  11.     int count = db.update(User.TABLE_NAME, values, selection, selectionArgs);
  12.     getContext().getContentResolver().notifyChange(uri, null); // 通知观察者
  13.     return count;
  14. }
  15. @Override
  16. public int delete(Uri uri, String selection, String[] selectionArgs) {
  17.     SQLiteDatabase db = dbHelper.getWritableDatabase();
  18.     int count = db.delete(User.TABLE_NAME, selection, selectionArgs);
  19.     getContext().getContentResolver().notifyChange(uri, null); // 通知观察者
  20.     return count;
  21. }
复制代码
总结

ContentProvider是Android中用于实现应用数据共享的紧张组件。通过定义统一的API接口,ContentProvider允许不同应用安全地访问和利用数据。上述示例展示了怎样创建和利用一个简单的ContentProvider,通过数据库管理用户信息,方便其他应用进行数据交互,以及通过利用ContentObserver,Android应用能够高效地监听ContentProvider的数据变化,从而实时更新UI或处理其他相关逻辑。这种机制使得应用能够保持数据的实时性,增强用户体验。理解怎样实现和利用ContentObserver对于开辟需要数据同步的应用至关紧张,能够帮助开辟者更好地设计数据共享的应用架构。
参考

https://medium.com/@myofficework000/content-provider-in-android-for-beginners-7a1717821546

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

小秦哥

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表