万书网 > 文学作品 > Android从入门到精通 > 第130页

第130页





图11.6 Cursor接口继承关系

说明:  圆角矩形表示接口,矩形表示类。

由于这些ContentProvider方法能被位于不同进程和线程的不同ContentResolver对象调用,它们必须以线程安全的方式实现。

此外,开发人员也可以调用ContentResolver.notifyChange()方法,以便在数据修改时通知监听器。

除了定义子类自身,还应采取一些措施以简化客户端工作并让类更加易用:

(1)定义public  static  final  Uri  CONTENT_URI变量(CONTENT_URI是变量名称)。该字符串表示自定义的Content  Provider处理的完整content:URI。开发人员必须为该值定义唯一的字符串。最佳的解决方式是使用Content  Provider的完整类名(小写)。例如,EmployeeProvider的URI可能按如下方式定义:

public  static  final  Uri  CONTENT_URI  =  Uri.parse("content://com.mingrisoft.employeeprovider");

如果provider包含子表,也应该为各个子表定义URI。这些URI应该有相同的authority(因为它标识Content  Provider),使用路径进行区分,例如:

content://com.mingrisoft.employeeprovider/dba



content://com.mingrisoft.employeeprovider/programmer



content://com.mingrisoft.employeeprovider/ceo

(2)定义Content  Provider将返回给客户端的列名。如果开发人员使用底层数据库,这些列名通常与SQL数据库列名相同。同样,定义public  static  String常量,客户端用它们来指定查询中的列和其他指令。确保包含名为“_ID”的整数列来作为记录的ID值。无论记录中其他字段是否唯一,如URL,开发人员都应该包含该字段。如果打算使用SQLite数据库,_ID字段类型如下:

INTEGER  PRIMARY  KEY  AUTOINCREMENT

(3)仔细注释每列的数据类型,客户端需要使用这些信息来读取数据。

(4)如果开发人员正在处理新数据类型,则必须定义新的MIME类型,以便在ContentProvider.  getType()方法实现中返回。

(5)如果开发人员提供的byte数据太大而不能放到表格中,如bitmap文件,提供给客户端的字段应该包含content:URI字符串。

11.3.2 声明Content  Provider

为了让Android系统知道开发人员编写的Content  Provider,应该在应用程序的AndroidManifest.xml文件中定义元素。没有在配置文件中声明的自定义Content  Provider,对于Android系统不可见。

name属性的值是ContentProvider类的子类的完整名称;authorities属性是provider定义的content:URI中authority部分;ContentProvider的子类是EmployeeProvider。元素应该如下:




android:authorities="com.mingrisoft.employeeprovider"



.  .  .  />





注意:  authorities属性删除了content:URI中的路径部分。

其他属性能设置读写数据的权限、提供显示给用户的图标或文本、启用或禁用provider等。如果数据不需要在多个运行的Content  Provider间同步,则设置multiprocess为true。这允许在各个客户端进程创建一个provider实例,从而避免执行IPC。





11.4 经典范例

11.4.1 查询联系人姓名和电话

例11.2   在Eclipse中创建Android项目,名称为11.2,实现查询当前联系人应用中联系人的姓名和电话。(实例位置:光盘\TM\sl\11\11.2)

(1)修改res\layout\main.xml文件,设置背景图片和标签属性,代码如下:








android:layout_width="fill_parent"



android:layout_height="fill_parent"



android:background="@drawable/background"



android:orientation="vertical"  >






android:id="@+id/result"



android:layout_width="wrap_content"



android:layout_height="wrap_content"



android:textColor="@android:color/black"



android:textSize="25dp"  />





(2)创建RetrieveDataActivity类,该类继承了Activity类。在onCreate()方法中获得布局文件中定义的标签,在自定义的getQueryData()方法中获得查询数据,代码如下:

public  class  RetrieveDataActivity  extends  Activity  {



private  String[]  columns  =  {  Contacts._ID,  //获得ID值



Contacts.DISPLAY_NAME,  //获得姓名



Phone.NUMBER,  //获得电话



Phone.CONTACT_ID,  };



public  void  onCreate(Bundle  savedInstanceState)  {



super.onCreate(savedInstanceState);



setContentView(R.layout.main);



TextView  tv  =  (TextView)  findViewById(R.id.result);  //获得布局文件中的标签



tv.setText(getQueryData());  //为标签设置数据



}



private  String  getQueryData()  {



StringBuilder  sb  =  new  StringBuilder();  //用于保存字符串