探索安卓内容提供者:构建、访问和管理数据【复习】

这篇具有很好参考价值的文章主要介绍了探索安卓内容提供者:构建、访问和管理数据【复习】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一 ContentProvider

  • 内容提供者(ContentProvider)是Android系统四大组件之一,它是不同应用程序之间进行数据共享的标准API,通过ContentResolver类可以访问ContentProvider中共享的数据。
  • ContentProvider的工作原理如下:
    探索安卓内容提供者:构建、访问和管理数据【复习】
    • A程序使用ContetntProvider暴露数据,才能被其他程序操作。B程序通过ContetnResolver操作A程序暴露出来的数据,A程序将操作的结果返回给ContentResoler,然后ContetnResolver再将操作的结果返回给B程序。

1.1 数据模型- ContentProvider 使用基于数据库模型的简单表格来提供需要共享的数据,在该表格中,每一表示一条记录,而每一列代表特定类型和含义的数据,并且其中每一条数据记录都包含一个名为“_ID”的字段类标识每条数据。

探索安卓内容提供者:构建、访问和管理数据【复习】

1.2 Uri(统一资源标识符)

  • 统一资源标识符(Uniform Resource Identifier,或URI)是一个用于标识某一资源名称的字符串。 该标识允许用户对任何(包括本地和互联网)的资源通过特定的协议进行交互操作。
  • ContentResolver提供一系列增删改查的方法对数据进行操作,并且这些方法以Uri的形式对外提供数据。
  • Uri为内容提供者中的数据建立了唯一标识符。它主要由三部分组成,scheme、authorities和path
    探索安卓内容提供者:构建、访问和管理数据【复习】

1.3 创建内容提供者

内容提供者创建步骤:

  1. 在程序包名处右击选择【New】->【Other】->【Content Provider】选项
  2. 输入内容提供者的Class Name(类名称)和URI Authorities(唯一标识,通常使用包名)
  3. 点击【Finish】按钮创建完成
private class MyObserver extends ContentObserver{
        public MyObserver(Handler handler) {
            super(handler);
        }
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
          }
        //还需要重写增删改查的方法
        //...
    }

1.4 清单文件

  • 内容提供者创建完成后,Android Studio会自动在AndroidManifest.xml中对内容提供者进行注册。
    <application ......>
        <provider
            android:name=".MyContentProvider"
            android:authorities="cn.itcast.mycontentprovider"
            android:enabled="true"
            android:exported="true" >
       </provider>
    </application>
  • provider中的android:name代表是继承于ContentProvider类的的全路径名称。
  • android:authorities:标识MyContentProvider提供的数据,该值可以是一个或者多个URI authority,authorities之间用分号隔开。
  • android:enabled:标识MyContentProvider提供的数据能否被系统实例化
  • android:exported:用于指示该服务是否能被其他程序应用组件调用或跟他交互; 取值为(true | false),如果设置成true,则能够被调用或交互,否则不能;设置为false时,只有同一个应用程序的组件或带有相同用户ID的应用程序才能启动或绑定该服务。

1.5 访问其他程序的数据

  • 在不同的应用程序之间交换数据时,应用程序会通过ContentProvider暴露自身数据,便通过ContentResolver对程序暴露的数据进行操作,因此 CntentProvider充当一个中介的角色。由于在使用ContentProvider暴露数据时,提供了相应的 Uri,因此在访问现有的CntentProvider时,要指定相应的 Uri,然后再通过ContentResolver对象来实现对数据的操作。

1.5.1 访问提供者【了解】

  • 从Uri访问 ContentProvider 的常用模式是使用 CursorLoader 在后台运行异步查询。UI中的 Activity 或 Fragment 会调用查询的 CursorLoader,其转而使用 ContentResolver 获取 ContentProvider。如此一来,用户便可在查询运行时继续使用UI。
  • ContentResolver对象在客户 app的进程中,ContentProvider对象在app中,它们之间自动处理IPC。ContentProvider也是数据存储同数据的外在表现的一个抽象层。
    探索安卓内容提供者:构建、访问和管理数据【复习】
  • 注意:为了存取provider,app通常在它的manifest文件中请求特定的权限。
  • 例如,为了从User Dictionary Provider中得到一个单词表,你需要调用ContentResolver.query()。query()方法实际调用User Dictionary Provider中的ContentProvider.query(),如下:
// Queries the user dictionary and returns results
mCursor = getContentResolver().query(
    UserDictionary.Words.CONTENT_URI,   // The content URI of the words table
    mProjection,                        // The columns to return for each row
    mSelectionClause                    // Selection criteria
    mSelectionArgs,                     // Selection criteria
    mSortOrder);                        // The sort order for the returned rows
  • 下表显示了query的参数同SQL SELECT语句的对应关系:
    探索安卓内容提供者:构建、访问和管理数据【复习】

1.5.2 通过ContentProvider查询其他程序数据

  • 步骤:
    1. 通过parse()方法解析Uri
    2. 通过query()方法查询数据
    3. 通过while()遍历查询到的数据
	//获取相应操作的Uri,Uri.parse()方法是将字符串转化成Uri对象。
    Uri uri = Uri.parse("content://cn.itcast.mycontentprovider/person"); 
    //获取ContentResolver对象
    ContentResolver resolver = context.getContentResolver();
    //通过ContentResolver对象查询数据
    Cursor cursor = resolver.query(Uri uri, String[] projection, String selection,
                                     String[] selectionArgs, String sortOrder);
    //通过while()循环将Cursor对象中的数据遍历出来
    while (cursor.moveToNext()) {
        String address = cursor.getString(0); 
        long date = cursor.getLong(1);
        int type = cursor.getInt(2);
   }
    cursor.close();

1.5.3 query方法

ContentResolver的query方法的函数接口如下:

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

参数说明:

  • uri:要查询的数据的地址。
  • projection:要查询的列,即需要返回的数据的字段。
  • selection:查询条件,即需要满足的约束条件。
  • selectionArgs:查询条件的参数,用于替换selection中的占位符。
  • sortOrder:查询结果的排序方式。
  • cancellationSignal:用于取消查询的信号。

返回值:

  • Cursor:查询结果的游标对象。

注意事项:

  • 如果查询不需要使用selection和selectionArgs,可以将它们设置为null。
  • 如果不需要排序,可以将sortOrder设置为null。
  • 如果不需要取消查询,可以将cancellationSignal设置为null。

示例代码:

Uri uri = Uri.parse("content://com.example.provider/user");
String[] projection = {"name", "age"};
String selection = "age > ?";
String[] selectionArgs = {"18"};
String sortOrder = "name ASC";
CancellationSignal cancellationSignal = null;
Cursor cursor = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal);

1.5.4 多学一招:UriMatcher类【了解】

  1. 初始化UriMatcher
    UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
    
  2. 将Uri注册到UriMatcher中
    matcher.addURI("cn.itcast.contentprovider", "people", PEOPLE);  
    matcher.addURI("cn.itcast.contentprovider", "person/#", PEOPLE_ID);
    
  3. 与已经注册的Uri进行匹配
    Uri uri = Uri.parse("content://" + "cn.itcast.contentprovider" + "/people");
    int match = matcher.match(uri);
    switch (match){
          case PEOPLE:
           //匹配成功后做的相关操作
           case PEOPLE_ID:
           //匹配成功后做的相关操作
    default:
        return null;
   }   

二 ContentObserver

  1. 内容观察者(ContentObserver)用于观察指定Uri所代表的数据的变化,当ContentObserver观察到指定Uri代表的数据发生变化时,就会触发onChange()方法,此时在onChange()方法中使用ContentResovler可以查询到变化的数据。
  2. 要使用ContentObserver观察数据变化,就必须在ContentProvider中调用ContentResolver的notifyChange()方法。
  • ContentObserver的工作原理如下:
    探索安卓内容提供者:构建、访问和管理数据【复习】
    • 使用contentObserver观察 A程序的数据时,首先要在 A程序的ContentProvider中调用ContentResolver的notifyChange()方法,调用此方法后,当 B操作程序作 A程序中的数据时, A程序会向消息中心发送数据变化的消息。此时C程序会观察到消息中心的数据有变化,会触发 ContentObserver的onChange()方法。
      创建ContentObserver的具体步骤如下:

2.1 创建ContentObserver

  1. 创建一个类继承自ContentObserver,并重写onChange方法。
    public class MyContentObserver extends ContentObserver {
    	//Handler对象是主线程中的Handler对象,也可以是其他线程中的Handler对象
        public MyContentObserver(Handler handler) {
            super(handler);
        }
    	//当MyContentObserver观察到Uri代表的数据发生变化时,程序回调用onChange()方法,并在该方法中处理相关的逻辑
        @Override
        public void onChange(boolean selfChange, Uri uri) {
            super.onChange(selfChange, uri);
            // 处理数据变化的逻辑
        }
    }
    
  2. 注册内容观察者
    ContentResolver resolver = getContentResolver();
    Uri uri = Uri.parse("content://aaa.bbb.ccc");
    resolver.registerContentObserver(uri, true, new MyContentObserver(new Handler());
    

参数说明:

  • uri:要监听的数据的地址。
  • notifyForDescendants:是否监听uri的所有子路径。
  1. 取消注册内容观察者
    getContentResolver().unregisterContentObserver(contentObserver);
    

通过以上步骤,就可以创建并使用ContentObserver来监听数据的变化。

注意事项:

  • ContentObserver只能监听ContentProvider中数据的变化,而不能监听其他的数据源。
  • ContentObserver的onChange方法在主线程中执行,如果需要执行耗时操作,建议在onChange中开启新的线程来处理。
  • ContentObserver的注册和取消注册应该在合适的时机进行,避免不必要的资源消耗。

  • 下面是一个完整的示例代码,演示如何创建和使用ContentObserver来监听数据的变化:

    public class MainActivity extends AppCompatActivity {
    
        private MyContentObserver contentObserver;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // 创建ContentObserver对象
            contentObserver = new MyContentObserver(new Handler());
            
            // 注册ContentObserver监听数据变化
            Uri uri = Uri.parse("content://com.example.provider/user");
            getContentResolver().registerContentObserver(uri, true, contentObserver);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            // 取消注册ContentObserver
            getContentResolver().unregisterContentObserver(contentObserver);
        }
    
        private class MyContentObserver extends ContentObserver {
            public MyContentObserver(Handler handler) {
                super(handler);
            }
    
            @Override
            public void onChange(boolean selfChange, Uri uri) {
                super.onChange(selfChange, uri);
                // 处理数据变化的逻辑
                Log.d("ContentObserver", "Data changed: " + uri.toString());
                // 可以在这里更新UI或执行其他操作
            }
        }
    }
    
    • 在上述示例中,在MainActivity的onCreate方法中创建了一个ContentObserver对象,并在onDestroy方法中取消注册。在MyContentObserver的onChange方法中,我们可以处理数据变化的逻辑,例如打印日志或更新UI。

2.2 补充:注册ContetnObserver的时机

  • 通常是在Activity、Fragment或Service等组件中的某个方法中注册ContentObserver来监听数据的变化。具体来说,可以在以下方法中注册ContentObserver:
    • 在Activity中,可以在onCreate方法中注册,然后在onDestroy方法中取消注册。
    • 在Fragment中,可以在onCreateView方法中注册,然后在onDestroyView方法中取消注册。
    • 在Service中,可以在onCreate方法中注册,然后在onDestroy方法中取消注册。
  • 具体选择,取决于业务需求和组件的生命周期。
  • 示例代码:
public class MainActivity extends AppCompatActivity {

    private MyContentObserver contentObserver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 创建ContentObserver对象
        contentObserver = new MyContentObserver(new Handler());

        // 注册ContentObserver监听数据变化
        Uri uri = Uri.parse("content://com.example.provider/user");
        getContentResolver().registerContentObserver(uri, true, contentObserver);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // 取消注册ContentObserver
        getContentResolver().unregisterContentObserver(contentObserver);
    }

    private class MyContentObserver extends ContentObserver {

        public MyContentObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            super.onChange(selfChange, uri);
            // 处理数据变化的逻辑
            Log.d("ContentObserver", "Data changed: " + uri.toString());
            // 可以在这里更新UI或执行其他操作
        }
    }
}

三 题目总结

  1. 简述内容提供者的工作原理
    • 假设B程序需要操作A程序数据库中的数据,一般需要A程序使用ContentProvider
      暴露数据,才能被其他程序操作。B程序通过ContentResolver操作A程序暴露出来的数据,而A程序会将操作结果返回给ContentResolver,然后ContentResolver再将操作结果返回给B程序。
  2. 简述内容观察者的工作原理
    • 使用ContentObserver观察A程序的数据时,首先要在A程序的ContentProvider中调用ContentResolver的notifyChange()方法。调用此方法后,当B程序操作A程序中的数据时,A程序会向“消息中心”发送数据变化的消息,此时C程序会观察到“消息中心”的数据有变化,会触发ContentObserver的onChange()方法。
  3. 在ContentProvider中ContentUris的作用是提供增删改查的方法

  • 在ContentProvider中,ContentUris类提供了一些方法,用于处理操作数据库中的数据的URI。这些方法可以帮助开发者在增删改查数据时,对URI进行解析和操作。
    具体来说,ContentUris的作用如下:
  1. 解析URI:ContentUris类的parseId()方法可以从URI中解析出对应的记录的ID。这个方法通常在查询或删除单个记录时使用。例如,可以使用ContentUris.parseId(uri)方法从URI中解析出记录的ID。
  2. 构建URI:ContentUris类的withAppendedId()方法可以将ID添加到URI中,构建出一个新的URI。这个方法通常在插入或更新记录时使用。例如,可以使用ContentUris.withAppendedId(baseUri, id)方法将ID添加到baseUri中,构建出新的URI。
  3. 获取记录的URI:ContentUris类的withAppendedId()方法也可以用于获取指定记录的URI。这个方法通常在查询或删除单个记录时使用。例如,可以使用ContentUris.withAppendedId(baseUri, id)方法获取指定记录的URI。
    通过使用ContentUris类的方法,开发者可以方便地解析和操作URI,从而实现对数据库中的数据进行增删改查的操作。

  1. 若要实现对系统联系人的增删改查,需要使用的系统ContentProvider的Uri为Contacts.Phones.CONTENT_URI
  2. 联系人信息内容提供者的主机名是com.android.contacts
    • 联系人信息的内容提供者的主机名是com.android.contacts,它是Android系统中默认的联系人信息提供者。通过该内容提供者,应用程序可以访问和操作设备上的联系人信息。
  3. 下面哪些功能需要用ContentProvider来实现()。
    A、读取系统中的短信内容
    B、建立一个数据库
    C、开机后自动启动一个程序
    D、播放一段音乐
  • 解析:

    • A、读取系统中的短信内容:需要使用ContentProvider来实现。Android系统中的短信内容存储在短信提供者中,开发者需要通过ContentResolver来查询短信提供者,从而读取系统中的短信内容。

    • B、建立一个数据库:不需要使用ContentProvider来实现。建立数据库可以直接使用SQLiteOpenHelper或Room等数据库框架来创建和管理数据库。

    • C、开机后自动启动一个程序:不需要使用ContentProvider来实现。开机后自动启动一个程序可以通过BroadcastReceiver和BOOT_COMPLETED广播来实现。

    • D、播放一段音乐:不需要使用ContentProvider来实现。播放音乐可以使用MediaPlayer或其他音频播放框架来实现,不涉及ContentProvider的使用。

    • 因此,只有读取系统中的短信内容需要使用ContentProvider来实现。其他功能不需要使用ContentProvider。文章来源地址https://www.toymoban.com/news/detail-498536.html

  1. 短信的内容提供者是()
    A、ContactProvider
    B、MessageProvider
    C、SmsProvider
    D、TelephonyProvider
  2. 在下列选项中,联系人信息内容提供者的主机名是()
    A、contact
    B、com.android.contacts
    C、com.android.provider.contact
    D、com.android.provider.contacts
  3. 内容提供者主要功能是实现跨程序共享数据的功能
  4. provider中的android:name代表是继承于ContentProvider类的的全路径名称。
  5. 为了解析Uri对象,Android系统提供了一个辅助工具类UriMatcher用于匹配Uri。
  6. Android中通过ContentResover.query()查询短信数据库的时候,第一个Uri参数如何写 contentprovider
  7. 内容观察者是通过观察消息中心来观察数据库的变化
  8. 消息中心是用来观察指定Uri所代表的数据
  9. 利用内容解析者读取短信数据库内容时,短信数据库SmsInfo表主要用来存储短信信息
  10. resolver.registerContentObserver()方法用于注册内容观察者
  11. 创建UriMatcher对象时调用UriMatcher(int code),参数通常使用UriMatcher.NO_MATCH,表示路径不满足条件返回_-1
  12. 当ContentObserver观察到指定Uri代表的数据发生变化时,就会触发ContentObserver的**onChange()**方法。
  13. 内容提供者把私有的数据给暴露出来,我们通过ContentResolver来进行查询数据
  14. 在Android中,是通过ContentResolver读取联系人信息的。
  15. 注册provider时需要指定两个属性android.name和android:authorities
  16. 短信数据是存放在sms表中的
  17. Android中通过内容提供者来读取联系人信息,data表用来保存联系人信息的.
    • Android中读取联系人信息 有三张关键的表1 data表用来存储联系人信息的表,2 raw_contacts 表用来存储一共有多少个联系人. 3 mimetype表用来区分联系人信息的表
  18. 在短信接收器案例中,注册短信内容观察者时,使用的到Uri是Content://sms/

四 补充

  1. 请简要说明 ContentProvider 对外共享数据的好处。
    • 通过 ContentProvider 共享数据统一数据访问方式,使用起来更规范,通过数据库存储并指定了 URI,只有通过特定 URI 才能访问数据,使数据更安全。
  2. 请简要说明 ContentProvider、ContentResolver 和 ContentObserver 之间的联系。
    • ContentProvider 可以共享自己的数据给外部应用访问,要访问 ContentProvider 暴露的数据就要用到 ContentResolver。
    • ContentObserver 就相当于中间人的角色,它可以事实监听ContentProvider 的 数 据 是 否 发 生 变 化 , 如 果 发 生 变 化 就 会 触 发 onChange() 方 法 ,Contentresolver 可以在 onChange()方法中查询的哪些数据发生了变化再对数据进行操作。

到了这里,关于探索安卓内容提供者:构建、访问和管理数据【复习】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringCloud Eureka注册服务提供者(七)

    这里我们在原来的服务提供者项目 microservice-student-provider-1001  上面直接修改: dependency     groupIdorg.springframework.cloud/groupId     artifactIdspring-cloud-starter-eureka/artifactId /dependency dependency     groupIdorg.springframework.cloud/groupId     artifactIdspring-cloud-starter-config/artifactId /dependency eurek

    2024年02月09日
    浏览(32)
  • RpcProvider(rpc服务提供者)实现思路

    上一节说到,如何将一个本地服务发布成远程服务,但没有说明一个rpc框架怎么进行调用的,看看上节代码 现在实现的发布服务方,那么显然Login方法是rpc框架帮我们调用的,什么时候调用?当rpc客户端通过网络发送rpc调用请求之后,这边接收到rpc请求,解析请求然后调用发

    2024年02月14日
    浏览(29)
  • 【spring cloud学习】4、创建服务提供者

    注册中心Eureka Server创建并启动之后,接下来介绍如何创建一个Provider并且注册到Eureka Server中,再提供一个REST接口给其他服务调用。 首先一个Provider至少需要两个组件包依赖:Spring Boot Web服务组件和Eureka Client组件。如下所示: Spring Boot Web服务组件用于提供REST接口服务,Eure

    2024年02月11日
    浏览(29)
  • 服务提供者 Eureka + 服务消费者(Rest + Ribbon)实战

    Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。简单来说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助你基于某

    2024年02月04日
    浏览(29)
  • 记一次dubbo消费者注册失败找不到服务提供者问题

    项目分多套环境,其中一套环境重新部署时,频繁出现消费者找不到服务提供者的错误 经过多次重启后才有可能恢复正常,而其他环境并没有发现此问题 怀疑点: 1.消费者和服务提供者dubbo版本对不上 2.服务提供者没有注册上服务 3.注册中心有问题 逐一排查: 1.消费者和服

    2023年04月18日
    浏览(29)
  • SpringCloud学习笔记(三)_服务提供者集群与服务发现Discovery

    既然SpringCloud的是微服务结构,那么对于同一种服务,当然不可能只有一个节点,需要部署多个节点 架构图如下: 由上可以看出存在多个同一种服务提供者(Service Provider) 搭建服务提供者集群 1、参考:SpringCloud 快速入门搭建单机版的:Eureka Server、Service Provider、Service Con

    2024年02月11日
    浏览(29)
  • dubbo启动报错 java.lang.reflect.InvocationTargetException null 没有提供者没有消费者

    启动dubbo时,控制台报错信息如下。 打开dubbo的服务注册中心发现 在网上查找了一番,网上的说发众说飞云,有人说要保证提供者和消费者的包名一致,也有人说是ip的问题要在host里面配置, 后来经过一番仔细查找发现不对的地方了 服务提供者的主类上没有配置注解,这个

    2024年02月13日
    浏览(34)
  • CSDN博客批量查询质量分https://yma16.inscode.cc/请求超时问题(设置postman超时时间)(接口提供者设置了nginx超时时间)

    https://yma16.inscode.cc/ 查询别人的一下子就返回了,查询我自己的,1分钟还不返回,然后就显示超时了。。 一开始我还以为是这个开源项目本身的问题,设置了请求超时时间,我还给它改了超时时间,后来发现不是的。。。 本来是100000的,我给改成1000000了,我对js代码不熟,

    2024年02月12日
    浏览(34)
  • 构建未来移动应用:探索安卓、iOS和HarmonyOS的技术之旅

    在移动应用开发领域,安卓、iOS和HarmonyOS是三个常见的操作系统。本文将对它们进行比较分析,并展示一些相关的代码示例。 安卓(Android) 安卓是由Google开发的移动操作系统,基于Linux内核。它具有开放源代码的特点,可以在各种设备上运行。以下是一个简单的安卓应用程

    2024年02月14日
    浏览(31)
  • “构建安全高效的前端权限控制系统:确保用户访问合适的内容“

    目录 引言 一、背景介绍 二 、具体实现方法 (1)用户角色管理 1. 安装依赖 2. 创建数据模型 3. 创建控制器 4. 创建路由 5. 配置应用程序 6. 测试接口 (2)前端路由控制 1. 安装Vue Router 2. 创建路由配置 3. 创建视图组件 4. 配置路由 5. 测试路由控制 (3) 页面元素展示控制 1. 创

    2024年02月19日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包