蹒跚走路的程序猿

Android ContentProvider的实现

  当Android中的应用需要访问其他应用的数据时,用ContentProvider可以很好的解决这个问题。今天介绍一下ContentProvider的用法。

  首先开发ContentProvider有两个步骤:

  1、开发一个ContentProvider的子类,该子类需要实现增、删、改、查等方法。

  2、在AndroidManifest.xml文件中注册该ContentProvider。

  下面通过一个实例来介绍一下ContentProvider到底怎么实现的。首先,我们也像系统一样把ContentProvider的Uri、数据列等信息以常量的形式公开出来、方便访问。为此,定义一个工具类,该类中只是包含一个public static的常量,该工具类的代码如下:

 1 public final class Words
 2 {
 3     // 定义该ContentProvider的Authority
 4     public static final String AUTHORITY 
 5         = "org.crazyit.providers.dictprovider";
 6     //定义一个静态内部类
 7     public static final class Word implements BaseColumns
 8     {
 9         // 定义Content所允许操作的3个数据列
10         public final static String _ID = "_id";
11         public final static String WORD = "word";
12         public final static String DETAIL = "detail";
13         // 定义该Content提供服务的两个Uri
14         public final static Uri DICT_CONTENT_URI = 
15             Uri.parse("content://" +  AUTHORITY + "/words");
16         public final static Uri WORD_CONTENT_URI = 
17             Uri.parse("content://" +  AUTHORITY + "/word");        
18     }
19 }

  上面的工具类只是定义了一些简单的常量的工具类,这个工具类的作用就是告诉其他应用访问该ContentProvider的一些常用的入口。
  接下来开发一个ContentProvider的子类,并重写其中的增、删、改、查等方法,代码如下:

  1 public class DictProvider extends ContentProvider
  2 {
  3     private static UriMatcher matcher
  4         = new UriMatcher(UriMatcher.NO_MATCH);
  5     private static final int WORDS = 1;
  6     private static final int WORD = 2;
  7     private MyDatabaseHelper dbOpenHelper;
  8     static
  9     {
 10         // 为UriMatcher注册两个Uri
 11         matcher.addURI(Words.AUTHORITY, "words", WORDS);
 12         matcher.addURI(Words.AUTHORITY, "word/#", WORD);
 13     }
 14     // 第一次调用该DictProvider时,系统先创建DictProvider对象,并回调该方法
 15     @Override
 16     public boolean onCreate()
 17     {
 18         dbOpenHelper = new MyDatabaseHelper(this.getContext(), "myDict.db3", 1);
 19         return true;
 20     }
 21     // 插入数据方法
 22     @Override
 23     public Uri insert(Uri uri, ContentValues values)
 24     {
 25         // 获得数据库实例
 26         SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
 27         // 插入数据,返回行ID
 28         long rowId = db.insert("dict", Words.Word._ID, values);
 29         // 如果插入成功返回uri
 30         if (rowId > 0)
 31         {
 32             // 在已有的 Uri的后面追加ID数据
 33             Uri wordUri = ContentUris.withAppendedId(uri, rowId);
 34             // 通知数据已经改变
 35             getContext().getContentResolver().notifyChange(wordUri, null);
 36             return wordUri;
 37         }
 38         return null;
 39     }
 40     // 删除数据的方法
 41     @Override
 42     public int delete(Uri uri, String selection, String[] selectionArgs)
 43     {
 44         SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
 45         // 记录所删除的记录数
 46         int num = 0;
 47         // 对于uri进行匹配。
 48         switch (matcher.match(uri))
 49         {
 50             case WORDS:
 51                 num = db.delete("dict", selection, selectionArgs);
 52                 break;
 53             case WORD:
 54                 // 解析出所需要删除的记录ID
 55                 long id = ContentUris.parseId(uri);
 56                 String where = Words.Word._ID + "=" + id;
 57                 // 如果原来的where子句存在,拼接where子句
 58                 if (selection != null && !selection.equals(""))
 59                 {
 60                     where = where + " and " + selection;
 61                 }
 62                 num = db.delete("dict", where, selectionArgs);
 63                 break;
 64             default:
 65                 throw new IllegalArgumentException("未知Uri:" + uri);
 66         }
 67         // 通知数据已经改变
 68         getContext().getContentResolver().notifyChange(uri, null);
 69         return num;
 70     }
 71     // 修改数据的方法
 72     @Override
 73     public int update(Uri uri, ContentValues values, String selection,
 74         String[] selectionArgs)
 75     {
 76         SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
 77         // 记录所修改的记录数
 78         int num = 0;
 79         switch (matcher.match(uri))
 80         {
 81             case WORDS:
 82                 num = db.update("dict", values, selection, selectionArgs);
 83                 break;
 84             case WORD:
 85                 // 解析出想修改的记录ID
 86                 long id = ContentUris.parseId(uri);
 87                 String where = Words.Word._ID + "=" + id;
 88                 // 如果原来的where子句存在,拼接where子句
 89                 if (selection != null && !selection.equals(""))
 90                 {
 91                     where = where + " and " + selection;
 92                 }
 93                 num = db.update("dict", values, where, selectionArgs);
 94                 break;
 95             default:
 96                 throw new IllegalArgumentException("未知Uri:" + uri);
 97         }
 98         // 通知数据已经改变
 99         getContext().getContentResolver().notifyChange(uri, null);
100         return num;
101     }
102     // 查询数据的方法
103     @Override
104     public Cursor query(Uri uri, String[] projection, String selection,
105         String[] selectionArgs, String sortOrder)
106     {
107         SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
108         switch (matcher.match(uri))
109         {
110             case WORDS:
111                 // 执行查询
112                 return db.query("dict", projection, selection, selectionArgs,
113                     null, null, sortOrder);
114             case WORD:
115                 // 解析出想查询的记录ID
116                 long id = ContentUris.parseId(uri);
117                 String where = Words.Word._ID + "=" + id;
118                 // 如果原来的where子句存在,拼接where子句
119                 if (selection != null && !"".equals(selection))
120                 {
121                     where = where + " and " + selection;
122                 }
123                 return db.query("dict", projection, where, selectionArgs, null,
124                     null, sortOrder);
125             default:
126                 throw new IllegalArgumentException("未知Uri:" + uri);
127         }
128     }
129     // 返回指定uri参数对应的数据的MIME类型
130     @Override
131     public String getType(Uri uri)
132     {
133         switch (matcher.match(uri))
134         {
135             // 如果操作的数据是多项记录
136             case WORDS:
137                 return "vnd.android.cursor.dir/org.crazyit.dict";
138                 // 如果操作的数据是单项记录
139             case WORD:
140                 return "vnd.android.cursor.item/org.crazyit.dict";
141             default:
142                 throw new IllegalArgumentException("未知Uri:" + uri);
143         }
144     }
145 }

上面的DictProvider类继承了ContentProvider,并实现了操作数据的增、删、改、查等方法。接下来需要在AndroidManitest.xml文件中注册该ContentProvider,代码:

1 <!-- 注册一个ContentProvider -->
2         <provider android:name=".DictProvider" 
3             android:authorities="org.crazyit.providers.dictprovider"/>

  至此,整个ContentProvider开发完成,为了测试它,我们需要新建一个工程。
  在新的工程里,我们需要把上面创建的工具类拷贝到新工程里,下面的是使用ContentProvider的代码:

 1 public class DictResolver extends Activity
 2 {
 3     ContentResolver contentResolver;
 4     Button insert = null;
 5     Button search = null;
 6     @Override
 7     public void onCreate(Bundle savedInstanceState)
 8     {
 9         super.onCreate(savedInstanceState);
10         setContentView(R.layout.main);
11         // 获取系统的ContentResolver对象
12         contentResolver = getContentResolver();
13         insert = (Button)findViewById(R.id.insert);
14         search = (Button)findViewById(R.id.search);    
15         // 为insert按钮的单击事件绑定事件监听器
16         insert.setOnClickListener(new OnClickListener()
17         {
18             @Override
19             public void onClick(View source)
20             {
21                 //获取用户输入
22                 String word = ((EditText)findViewById(R.id.word))
23                     .getText().toString();
24                 String detail = ((EditText)findViewById(R.id.detail))
25                     .getText().toString();
26                 //插入生词记录
27                 ContentValues values = new ContentValues();
28                 values.put(Words.Word.WORD , word);
29                 values.put(Words.Word.DETAIL , detail);
30                 contentResolver.insert(Words.Word.DICT_CONTENT_URI , values);
31                 //显示提示信息
32                 Toast.makeText(DictResolver.this, "添加生词成功!" , 8000)
33                     .show();
34             }            
35         });
36         // 为search按钮的单击事件绑定事件监听器
37         search.setOnClickListener(new OnClickListener()
38         {
39             @Override
40             public void onClick(View source)
41             {
42                 // 获取用户输入
43                 String key = ((EditText) findViewById(R.id.key)).getText()
44                     .toString();
45                 // 执行查询
46                 Cursor cursor = contentResolver.query(
47                     Words.Word.DICT_CONTENT_URI, null 
48                     , "word like ? or detail like ?"
49                     , new String[]{"%" + key + "%" , "%" + key + "%"} 
50                     , null);
51                 //创建一个Bundle对象
52                 Bundle data = new Bundle();
53                 data.putSerializable("data", converCursorToList(cursor));
54                 //创建一个Intent
55                 Intent intent = new Intent(DictResolver.this
56                     , ResultActivity.class);
57                 intent.putExtras(data);
58                 //启动Activity
59                 startActivity(intent);
60             }
61         });
62     }
63 
64     private ArrayList<Map<String, String>> converCursorToList(
65         Cursor cursor)
66     {
67         ArrayList<Map<String, String>> result 
68             = new ArrayList<Map<String, String>>();
69         // 遍历Cursor结果集
70         while (cursor.moveToNext())
71         {
72             // 将结果集中的数据存入ArrayList中
73             Map<String, String> map = new HashMap<String, String>();
74             // 取出查询记录中第2列、第3列的值
75             map.put(Words.Word.WORD, cursor.getString(1));
76             map.put(Words.Word.DETAIL, cursor.getString(2));
77             result.add(map);
78         }
79         return result;
80     }
81 }

至此,测试ContentProvider的关键代码已经给出了,希望能够帮助大家,在此也希望大家多多关注本人。

posted on 2013-08-18 21:26  蹒跚走路的程序猿  阅读(406)  评论(0编辑  收藏  举报

导航