zoukankan      html  css  js  c++  java
  • Android应用开发学习笔记之ContentProvider

    作者:刘昊昱 

    博客:http://blog.csdn.net/liuhaoyutz

    ContentProvider用于为其它应用程序提供共享数据,它为不同应用程序间共享数据提供了统一的操作接口。

    一、ContentProvider的Uri

    每个ContentProvider都有对应的Uri,例如,一个自定义的ContentProvider Uri格式如下:

    content://authority/path/id

    例如:

    content://com.liuhaoyu.myprovider/table1/10

    1、  content://是“scheme”,Android规定ContentProvider的scheme固定为content://

    2、  com.liuhaoyu.myprovider是“authority”,authority用于唯一标识这个ContentProvider,authority一般使用完整的类名来表示,以保证其唯一性。

    另外,对于自定义的ContentProvider,还需要在AndroidManifest.xml中指定authority对ContentProvider进行唯一标识。例如:

    <manifest.... >

       <applicationandroid:icon="@drawable/icon"android:label="@string/app_name">

          <provider android:name=".MyContentProvider"

               android:authorities="com.liuhaoyu.myprovider"/>

       </application>

    </manifest>

    3、  authority之后的部分,表示我们要操作的数据,包括“path”和“id”,具体包括几个字段,应该根据需要而定。例如:

             要操作table2表中的所有记录,则路径为table2

             要操作table2表中的ID为2的记录,则路径为table2/2

             要操作table2表中的ID为2的记录的name字段,则路径为table2/2/name

    如果要把字符串转换为Uri,可以使用Uri.parse()函数,例如:

    Uri uri = Uri.parse(“content://com.liuhaoyu.myprovider/table1/10/name”);

    二、Uri的辅助类

    因为Uri会经常用到,所以Android提供了两个Uri辅助类UriMatcher和ContentUris。UriMatcher用于对Uri进行匹配,ContentUris用于对Uri的ID部分进行操作。

    先来通过一个例子看UriMatcher的用法:

    UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    sMatcher.addURI("com.liuhaoyu.myprovider","person", 1);

    sMatcher.addURI("com.liuhaoyu.myprovider","person/#", 2);//#号为通配符

    switch (sMatcher.match(Uri.parse("content://com.liuhaoyu.myprovider/person/10"))){

      case 1

        break;

      case 2

        break;

      default:

        break;

    }

    首先通过UriMatcher.addURI()对URI进行注册。以后就可以使用UriMatcher.match()对要处理的Uri进行匹配,如果匹配成功,返回注册的返回码。

    ContentUris类有两个比较实用的方法:

    ContentUris.withAppendedId()函数用于将ID添加到路径后面。

    Uri uri = Uri.parse("content://com.liuhaoyu.myprovider/table1")

    Uri resultUri = ContentUris.withAppendedId(uri,1);

    生成的resultUri为:content://com.liuhaoyu.myprovider/1

    ContentUris.parseId()函数用于从Uri中分析出ID。

    Uri uri =Uri.parse("content://com.ljq.provider.personprovider/person/10")

    long personid = ContentUris.parseId(uri);//获取的结果为:10

    三、预定义ContentProvider

    Android提供了一些预定义的ContentProvider,包括声音、图片、视频、联系人等等,它们大多数位于android.provider包中,下面列出一些常用的预定义ContentProvider:

    Borwser:书签、浏览历史、搜索历史

    CallLog:通话历史

    Contacts:联系人

    MediaStore:声音、视频、图片

    四、自定义ContentProvider

    若要定义自己的ContentProvider,需要完成以下操作:

    (1)、建立数据存储系统。大多数ContentProvider使用Android文件存储方式或者SQlite数据库保存数据,但是开发者可以使用任何方式存储数据。Android提供了SQLiteOpenHelper类帮助创建数据库,SQLiteDatabase类帮助管理数据库。

    (2)、继承ContentProvider类来提供数据访问接口。一般需要实现ContentProvider类的如下成员函数:

    public class PersonContentProvider extendsContentProvider{

      public boolean onCreate()

      public Uri insert(Uri uri, ContentValues values)

      public int delete(Uri uri, String selection, String[] selectionArgs)

      public int update(Uri uri, ContentValues values, String selection,String[] selectionArgs)

      public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder)

      public String getType(Uri uri)

    }

    (3)、在应用程序的AndroidManifest.xml文件中声明ContentProvider。例如:

    <manifest.... >

       <applicationandroid:icon="@drawable/icon"android:label="@string/app_name">

          <provider android:name=".MyContentProvider"

               android:authorities="com.liuhaoyu.myprovider"/>

       </application>

    </manifest>

    五、使用ContentResolver

    ContentProvider内部如何保存数据由其设计者决定,但是所有的ContentProvider都实现了一组通用的方法,用来对数据进行增、删、改、查。其它应用程序对ContentProvider进行操作时,并不会直接调用ContentProvider实现的方法,而是通过ContentResolver类实现对ContentProvider的操作。

    可以通过Activity.getContentResolver()函数获取ContentResolver对象。

    ContentResolver类提供了对ContentProvider进行增、删、改、查的相应函数,具体可参考官方文档。

    六、监听ContentProvider的变化

    若访问者要监听ContentProvider的变化,可以使用ContentResolver.registerContentObserver()注册一个ContentObserver对象对指定ContentProvider进行监听,如果ContentProvider的数据发生了变化,则ContentObserver.onChange()方法会被调用,可以在该函数中进行相应处理。

    而在ContentProvider这边,当其中的数据发生变化时,需要调用ContentResolver.notifyChange()函数通知注册的ContentObserver。

    七、应用举例

    下面来看一个使用预定义的ContentProvider的例子,该程序运行效果如下:

    先来看主布局文件,其内容如下:

     

    <?xml version="1.0"encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
     
       <TextView
            android:id="@+id/result"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@android:color/white"
            android:textSize="25dp" />
     
    </LinearLayout>


    下面看主Activity文件,其内容如下:

    package com.liuhaoyu;
     
    import android.app.Activity;
    import android.content.ContentResolver;
    import android.database.Cursor;
    import android.os.Bundle;
    importandroid.provider.ContactsContract.Contacts;
    importandroid.provider.ContactsContract.CommonDataKinds.Phone;
    import android.widget.TextView;
     
    public class MainActivity extends Activity{
                private String[] columns = { Contacts._ID,
                         Contacts.DISPLAY_NAME,
                         Phone.NUMBER,
                         Phone.CONTACT_ID, };
     
                 public void onCreate(BundlesavedInstanceState) {
                     super.onCreate(savedInstanceState);
                     setContentView(R.layout.main);
                     TextView tv = (TextView)findViewById(R.id.result);
                     tv.setText(getQueryData());
                 }
     
                 private String getQueryData() {
     
                     StringBuilder sb = new StringBuilder();
                     ContentResolver resolver =getContentResolver();
                     Cursor cursor =resolver.query(Contacts.CONTENT_URI, null, null, null, null);
                     while (cursor.moveToNext()) {
                         int idIndex =cursor.getColumnIndex(columns[0]);
                         int displayNameIndex =cursor.getColumnIndex(columns[1]);
                         int id = cursor.getInt(idIndex);
                         String displayName = cursor.getString(displayNameIndex);
                         Cursor phone =resolver.query(Phone.CONTENT_URI, null, columns[3] + "=" + id, null,null);
                         while (phone.moveToNext()) {
                             int phoneNumberIndex =phone.getColumnIndex(columns[2]);
                             String phoneNumber =phone.getString(phoneNumberIndex);
                             sb.append(displayName + ":" + "
    " + phoneNumber + "
    ");
                         }
                     }
                     cursor.close();
                     return sb.toString();
                 }
    }


  • 相关阅读:
    关于Python解释器
    进程和线程
    Python
    高等数学
    关于Bulk加载模式
    使用Update Strategy组件无法进行delete操作
    3.15 晚会—「饿了么」之殇
    JavaScript 踩坑心得— 为了高速(下)
    JavaScript 踩坑心得— 为了高速(上)
    从零开始运维之旅:如何监控你的 Windows?
  • 原文地址:https://www.cnblogs.com/riskyer/p/3275605.html
Copyright © 2011-2022 走看看