轻松掌握:如何跨进程获取数据库数据? (跨进程获取数据库)

在软件开发过程中,获取数据库数据是非常常见的操作。然而,在实际的开发中,我们经常会遇到跨进程获取数据库数据的情况。这个时候,我们需要一些特殊的技巧来实现这个功能。本文将介绍如何跨进程获取数据库数据,让读者轻松掌握这个技巧。

之一步:使用ContentProvider

在Android中,ContentProvider是实现数据共享的主要方式。他能够将应用程序中的数据集映射到标准的Android接口上,从而让其他应用程序可以访问到这些数据。ContentProvider是安卓四大组件之一,可以对数据库进行操作。同时为其他APP跨进程访问数据库提供了良好的标准化API支持。

如果你的应用程序需要跨进程获取数据库数据,那么可以考虑使用ContentProvider。创建ContentProvider的方法有很多种,包括使用原生开发的方式,或者使用第三方框架。下面将以原生开发为例进行讲解。

第二步:创建MetaData

ContentProvider需要元数据信息来描述他所映射的数据集信息。在Android中,MetaData是一种用于描述元数据信息的标记。通过MetaData标记,ContentProvider能够了解到数据集的基本信息。

在创建ContentProvider时需要编写一个MetaData类并在清单文件中注册。这个类包含了数据库的基本信息,如数据库名称、版本号以及表的名称等信息。具体实现方法如下:

public class MyDatabaseMetaData implements BaseColumns {

// 这是Content Provider的基础信息

public static final String AUTHORITY = “com.example.MyDataProvider”;

public static final String DATABASE_NAME = “mydatabase.db”;

public static final int DATABASE_VERSION = 1;

private MyDatabaseMetaData() {

}

// 表的名字以及字段的名字

public static final String TABLE_NAME = “mytable”;

public static final String COLUMN_NAME = “name”;

public static final String COLUMN_AGE = “age”;

// 其他的元数据信息

}

第三步:实现ContentProvider

在创建了MetaData之后,我们就可以开始实现ContentProvider了。在实现ContentProvider的过程中,我们需要注意以下几点:

1、实现ContentProvider需要继承ContentProvider基类,并实现其中的方法。

2、实现ContentProvider的方法需要非常小心,因为他们会在不同的线程中被调用。

3、ContentProvider必须在AndroidManifest.xml中注册。

下面是一个实现ContentProvider的基本结构:

public class MyContentProvider extends ContentProvider {

// 这是ContentProvider的初始化方法

public boolean onenCreate() {

// 创建数据库和表

return true;

}

// 查询数据库,并将数据返回给调用者

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

String[] selectionArgs, String sort) {

// 查询数据库并返回Cursor

return null;

}

// 插入数据到数据库

public Uri insert(Uri uri, ContentValues values) {

// 将数据插入到数据库

return null;

}

// 更新数据库中的数据

public int update(Uri uri, ContentValues values, String selection,

String[] selectionArgs) {

// 更新数据库中的数据

return 0;

}

// 删除数据

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

// 删除数据库中的数据

return 0;

}

// 返回指定URI所对应的MIME类型信息,让外部应用程序可以得知你返回的数据类型

public String getType(Uri uri) {

// 返回指定URI所对应的MIME类型信息

return null;

}

}

第四步:使用ContentProvider来获取数据

一旦实现了ContentProvider,我们就可以通过ContentResolver来调用这些方法获取数据了。ContentResolver是Android中用来访问ContentProvider的类。他提供了对ContentProvider操作的高层次抽象,并保证了其线程安全。下面是一个使用ContentResolver获取数据的例子:

Cursor cursor = getContentResolver().query(Uri.parse(“content://com.example.MyDataProvider.mytable”), null, null, null, null);

如果查询成功,我们就可以从返回的Cursor中获取数据。

在这篇文章中,我们介绍了如何使用ContentProvider来跨进程获取数据库数据。具体实现包括创建MetaData、实现ContentProvider方法以及使用ContentResolver调用这些方法来获取数据。我们希望读者可以通过这些技巧轻松掌握跨进程获取数据库数据的方法,从而更好地完成Android应用程序的开发。

相关问题拓展阅读:

Android 开发中,有哪些坑需要注意

1. 为Activity声明系统配置变更事件

系统配置变更事件是指转屏,区域语言发生变化,屏幕尺寸发生变化等等,如果Activity没有声明处理这些事件,发生事件时,系统会把Activity杀掉然后重启,并尝试恢复状态,Activity有机会通过onSaveInstanceState()保存一些基本数据到Bundle中,然后此Bundle会在Activity的onCreate()中传递过去。虽然这貌似正常,但是这会引发问题,因为很多其他的东西比如Dialog等是要依赖于具体Activity实例的。所以这种系统默认行为通常都不是我们想要的。

为了避免这些系统默认行为,就需要为Activity声明这些配置,如下二个是每个Activity必须声明的:

几乎所有的Activity都要声明如上,为什么Android不把它们变成Default的呢?

2. 尽量使用Android的API

这好像是废话,在Android上面开发不用Android API用什么?因为Android几乎支持Java SE所有的API,所以有很多地方Android API与Java SE的API会有重复的地方,比如说对于文件的操作更好使用Android里面Context封装的API,而不要直接使用File对象:

Context.openFileOutput(String); // no File file = new File(String)

原因就是API里面会考虑到Android平台本身的特性;再如,少用Thread,而多使用AsyncTask等。

3. 要考虑到Activity和进程被杀掉的情况

如了通常情况退出Activity外,还有Activity因其他原因被杀的情况,比如系统内存过低,系统配置变更,有异常等等,要考虑和测试这种情况,特别是Activity处理重要的数据时,做好的数据的保存。

4. 小心多语言

有些语言真的很啰嗦,中文或英文很简短就能表达的事情到了其他语言就变的死长死长的,所以如果是wrap_content就可能把其他控制挤出可视范围; 如果是指定长度就可能显示不全。也要注意特殊语言比如那些从右向左读的语言。

5. 不要用四大组件去实现接口

一是组件的对象都比较大,实现接口比较浪费,而且让代码更不易读和理解; 另外更重要的是导致多方引用,可能会引发内存泄露。

6. 用getApplication()来取Context当参数

对于需要使用Context对象作为参数的函数,要使用getApplication()获取Context对象当参数,而不要使用this,除非你需要特定的组件实例!getApplication()返回的Context是属于Application的,它会在整个应用的生命周期内存在,远大于某个组件的生命周期,所以即使某个引用长期持有Context对象也不会引发内存泄露。

7. 主线程只做UI控制和Frameworks回调相关的事。附属线程只做费时的后台操作。交互只通过Handler。这样就可以避免大量的线程问题。

8. Frameworks的回调不要做太多事情仅做必要的初始化,其他不是很重要的事情可以放到其他线程中去做,或者用Handler Schedule到稍后再做。

9. 要考虑多分辨率

至少为hdpi, mdpi, ldpi准备图片和布局。元素的单位也尽可能的使用dip而不要用px。

10. 利用Android手机的硬键

几乎所有的Android手机都有BACK和MENU,它们的作用是返回和弹出菜单,所以就不要再在UI中设计返回按扭和菜单按扭。很多优秀的应用如随手记和微信都有返回键,他们之所以有是因为他们都是从iOS上移植过来的,为了保存体验的一致,所以也有了返回和菜单。但这不够Android化,一个纯正的Android是没有必须重复硬键的功能的。

1、不要排斥新技术和新工具。Android Studio 1.0 之后的版本,基本已经稳定到可以支持正常的工作开发的程度了。单纯就书写效率而言,Android Studio 带来的好处绝对大于它和Gradle的学习成本。JetBrains的IDE,用过都说好。还有就是适当的提升targetSdkVersion到新版本。

2、代码设计方面的问题,大部分都能在Android系统源码里找到解决方案。当你想设计一个新模块,或者实现一个新ui组件的时候,应该采用哪些设计模式、应该以哪种形式给外界提供接口之类的问题,大部分都可以参考Android系统的源码,找到实现方式。Google为安卓程序员提供了一座现成的宝库。

3、理解Android和Java内存管理方式,至少要理解垃圾回收和Java的引用。就好比学OC就要先理解黄金法则一样,而java的内存管理,其实比OC要好理解多了。这可能会帮助你大大减少程序异步操作产生的空指针崩溃。也会帮助你理解为什么滥用单例模式会导致内存的臃肿。还会帮助你养成不用“+”去连接超大字符串的好习惯。

4、ContentProvider并不是只有在跨进程共享数据的才有用,把数据库表映射到一个独立的uri是Google鼓励的实现方式。从设计上讲,用uri(统一资源标识符)去描述数据,肯定比sql语句要理想。从效果上讲,用CursorLoader读取数据是让iOS程序员都羡慕不已的事情,作为android程序员,何苦不用呢。

5、理解Activity任务栈。非Activity的Context对象如果直接启动Activity会报错,这只是一个表面现象,真正起作用的其实是Activity任务栈机制。理解Activity任务栈机制以及Activity的各种启动方式,会帮助解决大部分页面关系错乱问题,以及应用互相掉起、任务栏进入应用后台弹窗引起的各种问题。

6、对于一些奇葩的第三方ROM,调用其非主流api的时候,可以使用反射。

在适配一些第三方ROM的的时候,调用一些在开发环境中没有,但在运行环境中有的方法时,可以使用反射。比方说,华为双卡手机可能会提供获取第二块SIM卡信息的api,如果直接调用,在开发环境可能无法通过正常编译,用反射就没问题。这属于不得已而用反射的一种情况。

7、SQLite的锁,是数据库级别的锁,也就是说同一个数据库的写操作无法并发执行。所以,在数据库设计的时候,如果表太多,尽量将没有关联的表拆到多个数据库文件中。

8、Bitmap的内存占用问题。这是一个困扰2.X时代android程序员的问题。

1、不要排斥新技术和新工具。Android Studio 1.0 之后的版本,基本已经稳定到可以支持正常的工作开发的程度了。单纯就书写效率而言,Android Studio 带来的好处绝对大于它和Gradle的学习成本。JetBrains的IDE,用过都说好。还有就是适当的提升targetSdkVersion到新版本。

2、代码设计方面的问题,大部分都能在Android系统源码里找到解决方案。当你想设计一个新模块,或者实现一个新ui组件的时候,应该采用哪些设计模式、应该以哪种形式给外界提供接口之类的问题,大部分都可以参考Android系统的源码,找到实现方式。Google为安卓程序员提供了一座现成的宝库。

3、理解Android和Java内存管理方式,至少要理解垃圾回收和Java的引用。就好比学OC就要先理解黄金法则一样,而java的内存管理,其实比OC要好理解多了。这可能会帮助你大大减少程序异步操作产生的空指针崩溃。也会帮助你理解为什么滥用单例模式会导致内存的臃肿。还会帮助你养成不用“+”去连接超大字符串的好习惯。

4、ContentProvider并不是只有在跨进程共享数据的才有用,把数据库表映射到一个独立的uri是Google鼓励的实现方式。从设计上讲,用uri(统一资源标识符)去描述数据,肯定比sql语句要理想。从效果上讲,用CursorLoader读取数据是让iOS程序员都羡慕不已的事情,作为android程序员,何苦不用呢。

5、理解Activity任务栈。非Activity的Context对象如果直接启动Activity会报错,这只是一个表面现象,真正起作用的其实是Activity任务栈机制。理解Activity任务栈机制以及Activity的各种启动方式,会帮助解决大部分页面关系错乱问题,以及应用互相掉起、任务栏进入应用后台弹窗引起的各种问题。

6、对于一些奇葩的第三方ROM,调用其非主流api的时候,可以使用反射。

在适配一些第三方ROM的的时候,调用一些在开发环境中没有,但在运行环境中有的方法时,可以使用反射。比方说,华为双卡手机可能会提供获取第二块SIM卡信息的api,如果直接调用,在开发环境可能无法通过正常编译,用反射就没问题。这属于不得已而用反射的一种情况。

7、SQLite的锁,是数据库级别的锁,也就是说同一个数据库的写操作无法并发执行。所以,在数据库设计的时候,如果表太多,尽量将没有关联的表拆到多个数据库文件中。

8、Bitmap的内存占用问题。这是一个困扰2.X时代android程序员的问题。

参考如下

1、不要排斥新技术和新工具。

Android Studio 1.0 之后的版本,基本已经稳定到可以支持正常的工作开发的程度了。单纯就书写效率而言,Android Studio 带来的好处绝对大于它和Gradle的学习成本。JetBrains的IDE,用过都说好。

还有就是适当的提升targetSdkVersion到新版本。

2、代码设计方面的问题,大部分都能在Android系统源码里找到解决方案。

当设计一个新模块,或者实现一个新ui组件的时候,应该采用哪些设计模式、应该以哪种形式给外界提供接口之类的问题,大部分都可以参考Android系统的源码,找到实现方式。Google为安卓程序员提供了一座现成的宝库。

3、理解Android和Java内存管理方式,至少要理解垃圾回收和Java的引用。

就好比学OC就要先理解黄金法则一样,而java的内存管理,其实比OC要好理解多了。

这可能会帮助大大减少程序异步操作产生的空指针崩溃。也会帮助理解为什么滥用单例模式会导致内存的臃肿。还会帮助养成不用“+”去连接超大字符串的好习惯。

4、ContentProvider并不是只有在跨进程共享数据的才有用,把数据库表映射到一个独立的uri是Google鼓励的实现方式。

从设计上讲,用uri(统一资源标识符)去描述数据,肯定比sql语句要理想。

从效果上讲,用CursorLoader读取数据是让iOS程序员都羡慕不已的事情,作为android程序员,何苦不用呢。

5、理解Activity任务栈。

非Activity的Context对象如果直接启动Activity会报错,这只是一个表面现象,真正起作用的其实是Activity任务栈机制。

理解Activity任务栈机制以及Activity的各种启动方式,会帮助解决大部分页面关系错乱问题,以及应用互相掉起、任务栏进入应用、后台弹窗引起的各种问题。

6、对于一些奇葩的第三方ROM,调用其非主流api的时候,可以使用反射。

在适配一些第三方ROM的的时候,调用一些在开发环境中没有,但在运行环境中有的方法时,可以使用反射。比方说,华为双卡手机可能会提供获取第二块SIM卡信息的api,如果直接调用,在开发环境可能无法通过正常编译,用反射就没问题。这属于不得已而用反射的一种情况。

7、SQLite的锁,是数据库级别的锁,也就是说同一个数据库的写操作无法并发执行。

所以,在数据库设计的时候,如果表太多,尽量将没有关联的表拆到多个数据库文件中。

8、Bitmap的内存占用问题。

这是一个困扰2.X时代android程序员的问题。

2.X时代Bitmap对象虽然存储在堆内存中,但是用了一个byte数组存储其像素信息。通过计数器来记录该像素信息被引用的个数。有人认为这个byte数组在native堆中,但事实上它也在堆中。

只有在使用者调用recycle()后,Bitmap对象才会释放像素信息,才会在失去引用后,被垃圾回收机制销毁。再加上DVM的heap size有严格的阀值,所以在使用大量图片资源的时候,及其容易发生OOM。

解决办法一般都是,用一个哈希表存储Bitmap对象的软引用,作为内存缓存,并在适当时机掉用其recycle()。

3.0以上版本Bitmap对象可以通过垃圾回收机制完全销毁,理论上不用再调用recycle()。

为Activity声明系统配置变更事件

系统配置变更事件是指转屏,区域语言发生变化,屏幕尺寸发生变化等等,如果Activity没有声明处理这些事件,发生事件时,系统会把Activity杀掉然后重启,并尝试恢复状态,Activity有机会通过onSaveInstanceState()保存一些基本数据到Bundle中,然后此Bundle会在Activity的onCreate()中传递过去。虽然这貌似正常,但是这会引发问题,因为很多其他的东西比如Dialog等是要依赖于具体Activity实例的。所以这种系统默认行为通常都不是我们想要的。

为了避免这些系统默认行为,就需要为Activity声明这些配置,如下二个是每个Activity必须声明的:

几乎所有的Activity都要声明如上,为什么Android不把它们变成Default的呢?

2. 尽量使用Android的API

这好像是废话,在Android上面开发不用Android API用什么?因为Android几乎支持Java SE所有的API,所以有很多地方Android API与Java SE的API会有重复的地方,比如说对于文件的操作更好使用Android里面Context封装的API,而不要直接使用File对象:

Context.openFileOutput(String); // no File file = new File(String)

原因就是API里面会考虑到Android平台本身的特性;再如,少用Thread,而多使用AsyncTask等。

3. 要考虑到Activity和进程被杀掉的情况

如了通常情况退出Activity外,还有Activity因其他原因被杀的情况,比如系统内存过低,系统配置变更,有异常等等,要考虑和测试这种情况,特别是Activity处理重要的数据时,做好的数据的保存。

4. 小心多语言

有些语言真的很啰嗦,中文或英文很简短就能表达的事情到了其他语言就变的死长死长的,所以如果是wrap_content就可能把其他控制挤出可视范围; 如果是指定长度就可能显示不全。也要注意特殊语言比如那些从右向左读的语言。

5. 不要用四大组件去实现接口

一是组件的对象都比较大,实现接口比较浪费,而且让代码更不易读和理解; 另外更重要的是导致多方引用,可能会引发内存泄露。

6. 用getApplication()来取Context当参数

对于需要使用Context对象作为参数的函数,要使用getApplication()获取Context对象当参数,而不要使用this,除非你需要特定的组件实例!getApplication()返回的Context是属于Application的,它会在整个应用的生命周期内存在,远大于某个组件的生命周期,所以即使某个引用长期持有Context对象也不会引发内存泄露。

7. 主线程只做UI控制和Frameworks回调相关的事。附属线程只做费时的后台操作。交互只通过Handler。这样就可以避免大量的线程问题。

8. Frameworks的回调不要做太多事情仅做必要的初始化,其他不是很重要的事情可以放到其他线程中去做,或者用Handler Schedule到稍后再做。

9. 要考虑多分辨率

至少为hdpi, mdpi, ldpi准备图片和布局。元素的单位也尽可能的使用dip而不要用px。

10. 利用Android手机的硬键

几乎所有的Android手机都有BACK和MENU,它们的作用是返回和弹出菜单,所以就不要再在UI中设计返回按扭和菜单按扭。很多优秀的应用如随手记和微信都有返回键,他们之所以有是因为他们都是从iOS上移植过来的,为了保存体验的一致,所以也有了返回和菜单。但这不够Android化,一个纯正的Android是没有必须重复硬键的功能的。

关于跨进程获取数据库的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » 轻松掌握:如何跨进程获取数据库数据? (跨进程获取数据库)