android四大组件之ContentProvider(二)
ContentProvider学习笔记
上一章节我们编写了自定义的一个StudentProvider,他提供了两种供外界访问数据的方式,content://come.demo.sqlite.studentprovider/t_student和content://come.demo.sqlite.studentprovider/t_student/#,这一章我们将讲解其他应用程序将如何来访问StudentProvider中的数据。
1、ContentResolver类介绍
我们知道StudentProvider继承了ContentProvider类,并实现了insert(),update(),delete(),query(),getType()等方法,同样的ContentResolver这个类也提供了insert(),update(),delete(),query()方法,当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法
ContentResolver 类提供了与ContentProvider类相同签名的四个方法:
public Uri insert(Uri uri, ContentValues values):该方法用于往ContentProvider添加数据。
public int delete(Uri uri, String selection, String[] selectionArgs):该方法用于从ContentProvider删除数据。
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs):该方法用于更新ContentProvider中的数据。
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder):该方法用于从ContentProvider中获取数据。
2、实例:对数据库表t_student的增删改查操作
(1)布局文件main.xml
<?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:id="@+id/btnAdd1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="插入数据1" /> <Button android:id="@+id/btnAdd2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="插入数据2" /> <Button android:id="@+id/btnSearch1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="查询数据1" /> <Button android:id="@+id/btnSearch2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="查询数据2" /> <Button android:id="@+id/btnUpdate1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="修改数据1" /> <Button android:id="@+id/btnUpdate2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="修改数据2" /> <Button android:id="@+id/btnDelete1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="删除数据1" /> <Button android:id="@+id/btnDelete2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="删除数据2" /> </LinearLayout>
(2)MainActivity来实现具体的操作
package com.demo.contentprovider; 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.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; /** * 使用ContentResolver实现对数据库表t_student的操作 * @author yinbenyang */ public class MainActivity extends Activity { private Button btnAdd1, btnAdd2, btnSearch1, btnSearch2, btnUpdate1, btnUpdate2, btnDelete1, btnDelete2; //匹配content://come.demo.sqlite.studentprovider/t_student路径 private static final int ONE = 1; //匹配content://come.demo.sqlite.studentprovider/t_student/ private static final int TWO = 2; //日志输出 private static final String TAG = "ContentProvider"; //定义的一个Uri,这个是StudentProvider提供的一个内容提供者 private static String CONTENT_URI = "content://come.demo.sqlite.studentprovider/t_student"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btnAdd1 = (Button) findViewById(R.id.btnAdd1); btnAdd2 = (Button) findViewById(R.id.btnAdd2); btnUpdate1 = (Button) findViewById(R.id.btnUpdate1); btnUpdate2 = (Button) findViewById(R.id.btnUpdate2); btnSearch1 = (Button) findViewById(R.id.btnSearch1); btnSearch2 = (Button) findViewById(R.id.btnSearch2); btnDelete1 = (Button) findViewById(R.id.btnDelete1); btnDelete2 = (Button) findViewById(R.id.btnDelete2); btnAdd1.setOnClickListener(listener); btnAdd2.setOnClickListener(listener); btnUpdate1.setOnClickListener(listener); btnUpdate2.setOnClickListener(listener); btnSearch1.setOnClickListener(listener); btnSearch2.setOnClickListener(listener); btnDelete1.setOnClickListener(listener); btnDelete2.setOnClickListener(listener); } private OnClickListener listener = new OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnAdd1: add(ONE); break; case R.id.btnAdd2: add(TWO); break; case R.id.btnUpdate1: update(ONE); break; case R.id.btnUpdate2: update(TWO); break; case R.id.btnDelete1: delete(ONE); break; case R.id.btnDelete2: delete(TWO); break; case R.id.btnSearch1: search(ONE); break; case R.id.btnSearch2: search(TWO); break; default: break; } } }; // 查询数据 private void search(int type) { ContentResolver resolver = getContentResolver(); Uri url = null; // 指定查询的列名 String projection[] = new String[] { "sid", "sname", "age" }; // 查询的条件 String selection = ""; // 查询条件的参数值 String[] selectionArgs = null; // 指定是否排序以及使用排序是时的排序规则 String sortOrder = ""; // 查询结果为一个Cursor Cursor cursor = null; switch (type) { case ONE: // parse方法通过传入一个字符串来构造一个Uri对象 url = Uri.parse(CONTENT_URI); selection = "sid < ?"; selectionArgs = new String[] { "3" }; cursor = resolver.query(url, projection, selection, selectionArgs, sortOrder); while (cursor.moveToNext()) { Log.i(TAG, "sid=" + cursor.getInt(0) + ",sname=" + cursor.getString(1) + ",age=" + cursor.getShort(2)); Toast.makeText( this, "sid=" + cursor.getInt(0) + ",sname=" + cursor.getString(1) + ",age=" + cursor.getShort(2), Toast.LENGTH_SHORT) .show(); } break; case TWO: // 此时指定查询id为1的学生信息 url = ContentUris.withAppendedId(Uri.parse(CONTENT_URI),1); selection = null; cursor = resolver.query(url, projection, selection, selectionArgs, sortOrder); while (cursor.moveToNext()) { Log.i(TAG, "sid=" + cursor.getInt(0) + ",sname=" + cursor.getString(1) + ",age=" + cursor.getShort(2)); Toast.makeText( this, "sid=" + cursor.getInt(0) + ",sname=" + cursor.getString(1) + ",age=" + cursor.getShort(2), Toast.LENGTH_SHORT) .show(); } break; default: break; } } // 删除数据 private void delete(int type) { ContentResolver resolver = getContentResolver(); Uri url = null; String where = ""; String[] selectionArgs = null; switch (type) { case ONE: url = Uri.parse(CONTENT_URI); // 指定删除id为1,2的学生信息 where = "sid in(?,?)"; selectionArgs = new String[] { "1", "2" }; resolver.delete(url, where, selectionArgs); break; case TWO: // 指定删除id为3的学生信息 url = ContentUris.withAppendedId(Uri.parse(CONTENT_URI),3); Log.i(TAG, "url:" + url); where = null; resolver.delete(url, where, selectionArgs); break; default: break; } } // 修改数据 private void update(int type) { ContentResolver resolver = getContentResolver(); ContentValues values = new ContentValues(); Uri url = null; String where = ""; String[] selectionArgs = null; switch (type) { case ONE: url = Uri.parse(CONTENT_URI); values.put("sname", "update1"); values.put("age", 22); where = "sid = ?"; // 指定更新语句的条件(此时若不指定则是更新全部的数据) selectionArgs = new String[] { "1" }; // 指定占位符的数值 Log.i(TAG, resolver.update(url, values, where, selectionArgs) + ""); break; case TWO: // 此时的Uri中包含了需要更新数据的id,所以不再需要指定更新语句的条件和参数值 url = ContentUris.withAppendedId(Uri.parse(CONTENT_URI),2); values.put("sname", "update2"); values.put("age", 22); where = null; Log.i(TAG, resolver.update(url, values, where, selectionArgs) + ""); break; default: break; } } // 插入数据 private void add(int type) { ContentResolver resolver = getContentResolver(); ContentValues values = new ContentValues(); values.put("sname", "zhaobenshan"); values.put("age", 23); Uri url = null; switch (type) { case ONE: url = Uri.parse(CONTENT_URI); // insert()方法返回一个Uri对象,这个对象是新插入的数据的Uri Log.i(TAG, resolver.insert(url, values).toString()); break; case TWO: /** * 这个构造一个Uri为:content://com.demo.contentprovider.studentprovider/ * t_student/1,然后插入,实际上新插入的一条数据的id并不会为1, * 因为已经存在为1的数据了,所以这个和上面的写法一样,生成的数据的id为2 */ url = ContentUris.withAppendedId(Uri.parse(CONTENT_URI),1); // insert()方法返回一个Uri对象,这个对象是新插入的数据的Uri Log.i(TAG, resolver.insert(url, values).toString()); break; default: break; } } }
页面显示的布局效果:
而后我们还是利用命令去com.demo.sqlite.activity/database/data.db中查看t_student表
(1) 点击插入数据1或者插入数据2,查看数据:
(2)点击查询数据1,可以看到弹出了id为1和2的两条数据,点击查询数据2可以看到只弹出id为1的数据
(3)点击修改数据1将t_student表中sid为1的name改为update1,age改为22,点击修改数据2将sid为2的name改为update2,age改为22.
(4)点击删除数据1将id为1,2的学生信息删除:如图删除后只剩下id为3的学生信息
点击删除数据2将id为3的学生信息删除,如图,最后t_student表中已经没有学生信息了
后记:t_student表是SqliteDemo应用程序中的表数据,而现在通过ContentProviderDemo程序也可以实现对t_student表的操作,由此可见,我们的ContentProvider实现数据在应用程序间的共享了