前言
- 学到了contentProvider,记录一下学到的知识,写一个CRUD的案例
- 案例内容(Provider负责CRUD的持久层操作,Resolver对Provider返回的Uri或者Cursor数据进行解析)
1.Provider的代码逻辑
(1)创建数据库连接DBHelper类
- 使用到了SQLite,因此需要继承SQLiteOpenHelper
- 构造函数中,删除多余的传参,自己手动传一个表名,factory=null,version=1
- 然后再DBHelper启动的时候,onCreate中执行两段sql语句,建立person表,并先插入一条记录。
public class DBHelper extends SQLiteOpenHelper {
private static final String TAG = "DBHelper";
public DBHelper(@Nullable Context context) {
super(context, "wang.db", null, 1);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
Log.e(TAG, "onCreate()");
sqLiteDatabase.execSQL("create table person(_id integer primary key autoincrement, name varchar)");
sqLiteDatabase.execSQL("insert into person (name) values ('Tom')");
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
(2)创建一个自定义的Provider类
- 需要继承ContentProvider类,并重写其方法,方法中包括增删改查等方法。
- Provider并不需要和任何视图进行绑定。
- 记得在清单中对这个Provider进行注册!注册的时候需要写上intent-filter,因为需要别的app调用
- 下面代码我尽量注释地详细点。
public class PersonProvider extends ContentProvider {
private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
private DBHelper dbHelper;
static {
matcher.addURI("com.wang.ch07_provider.personprovider", "/person", 1);
matcher.addURI("com.wang.ch07_provider.personprovider", "/person/#", 2);
}
private static final String TAG = "PersonProvider";
public PersonProvider() {
Log.e(TAG, "PersonProvider()");
}
@Override
public boolean onCreate() {
Log.e(TAG, "onCreate()");
dbHelper = new DBHelper(getContext());
return false;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
@Nullable String[] selectionArgs,
@Nullable String sortOrder) {
Log.e(TAG, "query()");
int code = matcher.match(uri);
SQLiteDatabase database = dbHelper.getReadableDatabase();
if (code == 1) {
Cursor cursor = database.query("person", projection, selection, selectionArgs,
null, null, null);
return cursor;
} else if (code == 2) {
long id = ContentUris.parseId(uri);
Cursor cursor = database.query("person", projection, "_id=?",
new String[]{id + ""}, null, null, null);
return cursor;
} else {
throw new RuntimeException("查询URI不合法");
}
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
Log.d(TAG, "insert()");
int code = matcher.match(uri);
SQLiteDatabase database = dbHelper.getReadableDatabase();
if (code == 1) {
long id = database.insert("person", null, contentValues);
database.close();
return ContentUris.withAppendedId(uri, id);
} else {
database.close();
throw new RuntimeException("插入URI不合法");
}
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
Log.d(TAG, "delete()");
int code = matcher.match(uri);
SQLiteDatabase database = dbHelper.getReadableDatabase();
int deleteCount = -1;
if (code == 1) {
deleteCount = database.delete("person", selection, selectionArgs);
} else if (code == 2) {
deleteCount = database.delete("person", "_id=?", new String[]{ContentUris.parseId(uri) + ""});
} else {
database.close();
throw new RuntimeException("delete Uri 非法");
}
database.close();
return deleteCount;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String selection, @Nullable String[] selectionArgs) {
Log.d(TAG, "update()");
int code = matcher.match(uri);
int updateCount = -1;
SQLiteDatabase database = dbHelper.getReadableDatabase();
if (code == 1) {
updateCount = database.update("person", contentValues, selection, selectionArgs);
} else if (code == 2) {
updateCount = database.update("person", contentValues, "_id=?", new String[]{ContentUris.parseId(uri) + ""});
} else {
database.close();
throw new RuntimeException("update Uri 非法");
}
database.close();
return updateCount;
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
}
(3)在清单中注册该PersonProvider
- name就取全限定名称就好,具有唯一性
- authorities就取全限定名称的全小写
- exported为true,意味着别的app可以调用该provider
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wang.ch07_provider">
<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/Theme.Provider">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name="com.wang.ch07_provider.PersonProvider"
android:authorities="com.wang.ch07_provider.personprovider"
android:exported="true" />
</application>
</manifest>
2.Resolver的代码逻辑
(1)界面布局xml
- 来四个键就好,每个键都有一个onClick绑定的事件方法在MainActivity中进行监听。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="insert"
android:text="Insert" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="update"
android:text="Update" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="delete"
android:text="Delete" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="query"
android:text="Query" />
</LinearLayout>
- 长这样
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/043fa3ff15b4a5d40f327e0d9505d6af.png)
(2)MainActivity代码逻辑
- 首先在onCreate中加载布局
- 其次每个监听方法中的逻辑基本上一致:(1)获取resolver;(2)使用resolver,通过Uri和其他参数,来调用对应Provider中的对应方法,并处理返回的Uri或者数据库Cursor。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void insert(View view) {
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://com.wang.ch07_provider.personprovider/person/");
ContentValues contentValues = new ContentValues();
contentValues.put("name", "wang");
Uri insertUri = resolver.insert(uri, contentValues);
Toast.makeText(this, "添加学生1,姓名为:" + contentValues.get("name") +
"\n返回的uri为:" + insertUri.toString(), Toast.LENGTH_SHORT).show();
}
public void update(View view) {
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://com.wang.ch07_provider.personprovider/person/1");
ContentValues contentValues = new ContentValues();
contentValues.put("name", "update-Tom");
int updateRow = resolver.update(uri, contentValues, null, null);
Toast.makeText(this, "update row = " + updateRow, Toast.LENGTH_SHORT).show();
}
public void delete(View view) {
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://com.wang.ch07_provider.personprovider/person/2");
int deleteRow = resolver.delete(uri, null, null);
Toast.makeText(this, "update row = " + deleteRow, Toast.LENGTH_SHORT).show();
}
public void query(View view) {
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://com.wang.ch07_provider.personprovider/person/1");
Cursor cursor = resolver.query(uri, null, null, null, null);
if (cursor.moveToNext()) {
int id = cursor.getInt(0);
String name = cursor.getString(1);
Toast.makeText(this, "学生id为:" + id + "\n学生姓名为:" + name, Toast.LENGTH_SHORT).show();
}
}
}
完成