Android应用程序组件Content Provider在应用程序之间共享数据的原理分析(5)

简介:
 Step 22. SQLiteCursorDriver.query
      这个函数定义在frameworks/base/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java文件中:
  1. public class SQLiteDirectCursorDriver implements SQLiteCursorDriver {  
  2.     ......  
  3.   
  4.     public Cursor query(CursorFactory factory, String[] selectionArgs) {  
  5.         // Compile the query  
  6.         SQLiteQuery query = new SQLiteQuery(mDatabase, mSql, 0, selectionArgs);  
  7.   
  8.         try {  
  9.             ......  
  10.   
  11.             // Create the cursor  
  12.             if (factory == null) {  
  13.                 mCursor = new SQLiteCursor(mDatabase, this, mEditTable, query);  
  14.             } else {  
  15.                 mCursor = factory.newCursor(mDatabase, this, mEditTable, query);  
  16.             }  
  17.   
  18.             ......  
  19.             return mCursor;  
  20.         } finally {  
  21.             ......  
  22.         }  
  23.     }  
  24.   
  25.     ......  
  26. }  
      这里我们就可以清楚地看到,这个函数首先会根据数据库对象mDatabase和原生SQL语句来构造一个SQLiteQuery对象,这个对象的创建的过程中,就会解析这个原生SQL语句,并且创建好数据库查询计划,这样做的好处是等到真正查询的时候就可以马上从数据库中获得取数据了,而不用去分析和理解这个SQL字符串语句,这个就是所谓的SQL语句编译了。有了这个SQLiteQuery对象之后,再把它和数据库对象mDatabase等待信息一起来创建一个SQLiteCursor对象,于是,这个SQLiteCursor对象就圈定要将来要从数据库中获取的数据了。这一步执行完成之后,就把这个SQLiteCursor对象返回给上层,最终回到Step 18中的Transport类bulkQuery函数中。有了这个SQLiteCursor对象之后,就通过创建一个CursorToBulkCursorAdaptor对象来把它和匿名共享内存关联起来,这样,就为将来从数据库中查询得到的数据找到了归宿。
 
      CursorToBulkCursorAdaptor类定义在frameworks/base/core/java/android/database/CursorToBulkCursorAdaptor.java文件中,我们来看看它的对象的构造过程,即它的构造函数的实现:
  1. public final class CursorToBulkCursorAdaptor extends BulkCursorNative  
  2.         implements IBinder.DeathRecipient {  
  3.     ......  
  4.   
  5.     public CursorToBulkCursorAdaptor(Cursor cursor, IContentObserver observer, String providerName,  
  6.             boolean allowWrite, CursorWindow window) {  
  7.         try {  
  8.             mCursor = (CrossProcessCursor) cursor;  
  9.             if (mCursor instanceof AbstractWindowedCursor) {  
  10.                 AbstractWindowedCursor windowedCursor = (AbstractWindowedCursor) cursor;  
  11.                 ......  
  12.   
  13.                 windowedCursor.setWindow(window);  
  14.             } else {  
  15.                 ......  
  16.             }  
  17.         } catch (ClassCastException e) {  
  18.             ......  
  19.         }  
  20.           
  21.         ......  
  22.     }  
  23.   
  24.     ......  
  25. }  
      这里传进来的参数cursor的类型为SQLiteCursor,从上面的类图我们可以知道,SQLiteCursor实现了CrossProcessCursor接口,并且继承了AbstractWindowedCursor类,因此,上面第一个if语句的条件成立,于是就会把这个SQLiteCurosr对象转换为一个AbstractWindowedCursor对象,目的是为了调用它的setWindow函数来把传进来的CursorWindow对象window保存起来,以便后面用来保存数据。
 
      Step 23. AbstractWindowedCursor.setWindow
      这个函数定义在frameworks/base/core/java/android/database/AbstractWindowedCursor.java文件中:
  1. public abstract class AbstractWindowedCursor extends AbstractCursor  
  2. {  
  3.     ......  
  4.   
  5.     public void setWindow(CursorWindow window) {  
  6.         ......  
  7.   
  8.         mWindow = window;  
  9.     }  
  10.   
  11.     ......  
  12.   
  13.     protected CursorWindow mWindow;  
  14. }  
      这个函数很简单,只是把参数window保存在AbstractWindowedCursor类的成员变量mWindow中。注意,这个成员变量mWindow的访问权限为protected,即AbstractWindowedCursor的子类可以直接访问这个成员变量。
 
      这一步完成以后,就返回到前面的Step 14中去了,执行下面语句:
  1. if (bulkCursor != null) {  
  2.     reply.writeStrongBinder(bulkCursor.asBinder());  
  3.   
  4.     if (wantsCursorMetadata) {  
  5.         reply.writeInt(bulkCursor.count());  
  6.         reply.writeInt(BulkCursorToCursorAdaptor.findRowIdColumnIndex(  
  7.             bulkCursor.getColumnNames()));  
  8.     }  
  9. else {  
  10.     ......  
  11. }  
      这里的bulkCursor不为null,于是,就会把这个bulkCursor对象写入到数据流reply中,这个接口是要通过Binder进程间通信机制返回到第三方应用程序的,它的实际类型就是我们在前面Step 18中创建的CursorToBulkCursorAdaptor对象了。
 
      从前面的Step 14的分析中,我们知道,这里的布尔变量wantsCursorMetadata为true,于是就会把请求数据的行数以及数据行的ID列索引号一起写入到数据流reply中去了。这里,我们重点分析IBulkCursor接口的count函数,因为这个调用使得这个Content Provider会真正去执行数据库查询的操作。至于是如何得到从数据库查询出来的数据行的ID列的位置呢?回忆前面这篇文章 Android应用程序组件Content Provider应用实例 ,我们提到,如果我们想将数据库表中的某一列作为数据行的ID列的话,那么就必须把这个列的名称设置为"_id",这里的BulkCursorToCursorAdaptor类的静态成员函数findRowIdColumnIndex函数就是根据这个列名"_id"来找到它是位于数据行的第几列的。
      CursorToBulkCursorAdaptor类定义在frameworks/base/core/java/android/database/CursorToBulkCursorAdaptor.java文件中,它的count成员函数的实现如下所示:
  1. public final class CursorToBulkCursorAdaptor extends BulkCursorNative  
  2.         implements IBinder.DeathRecipient {  
  3.     ......  
  4.   
  5.     public int count() {  
  6.         return mCursor.getCount();  
  7.     }  
  8.   
  9.     ......  
  10. }  
      它的成员变量mCursor即为在前面Step 22中创建的SQLiteCursor对象,于是,下面就会执行SQLiteCursor类的getCount成员函数。




本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/967009,如需转载请自行联系原作者
目录
相关文章
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
1608 4
|
11月前
|
安全 数据库 Android开发
在Android开发中实现两个Intent跳转及数据交换的方法
总结上述内容,在Android开发中,Intent不仅是活动跳转的桥梁,也是两个活动之间进行数据交换的媒介。运用Intent传递数据时需注意数据类型、传输大小限制以及安全性问题的处理,以确保应用的健壯性和安全性。
671 11
|
存储 XML Java
Android 文件数据储存之内部储存 + 外部储存
简介:本文详细介绍了Android内部存储与外部存储的使用方法及核心原理。内部存储位于手机内存中,默认私有,适合存储SharedPreferences、SQLite数据库等重要数据,应用卸载后数据会被清除。外部存储包括公共文件和私有文件,支持SD卡或内部不可移除存储,需申请权限访问。文章通过代码示例展示了如何保存、读取、追加、删除文件以及将图片保存到系统相册的操作,帮助开发者理解存储机制并实现相关功能。
2908 2
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
989 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
缓存 Java 数据库
Android的ANR原理
【10月更文挑战第18天】了解 ANR 的原理对于开发高质量的 Android 应用至关重要。通过合理的设计和优化,可以有效避免 ANR 的发生,提升应用的性能和用户体验。
834 56
|
存储 大数据 数据库
Android经典面试题之Intent传递数据大小为什么限制是1M?
在 Android 中,使用 Intent 传递数据时存在约 1MB 的大小限制,这是由于 Binder 机制的事务缓冲区限制、Intent 的设计初衷以及内存消耗和性能问题所致。推荐使用文件存储、SharedPreferences、数据库存储或 ContentProvider 等方式传递大数据。
918 0
|
Linux API Android开发
Android中mmap原理及应用简析
Android中mmap原理及应用简析
733 0
Android中mmap原理及应用简析
|
前端开发 Java API
Android drawFunctor原理及应用
一. 背景AntGraphic项目Android平台中使用了基于TextureView环境实现GL渲染的技术方案,而TextureView需使用与Activity Window独立的GraphicBuffer,RenderThread在上屏TextureView内容时需要将GraphicBuffer封装为EGLImage上传为纹理再渲染,内存占用较高。为降低内存占用,经仔细调研Android源码,
820 0
|
8月前
|
移动开发 前端开发 Android开发
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
1450 12
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
8月前
|
移动开发 JavaScript 应用服务中间件
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
1025 5
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡

热门文章

最新文章