关闭ContentProvider中的数据库
2016-05-28 20:33
387 查看
这个星期,我一直在学习所有关于ContentProvider的的SQLiteOpenHelper的类来管理提供商内部的数据库的创建和升级。具体地讲,我一直在读通过记事本的例子来自SDK的samples目录。 现在,我可以看到,SQLiteOpenHelper的有一个close()方法。我知道,闲置数据库的开放是不好的做法,可以泄漏和诸如此类的东西(除非这是朝着正确的方向)。如果我的类中的活动
CodeGo.net,那么我会简单地调用close()方法中的onDestroy()方法,但据我所知,ContentProvider的不具有生命周期的活动做。记事本的代码似乎永远不会调用close(),所以我想它是由SQLiteOpenHelper的或其它的一块拼图处理,但我真的很想知道。我真的不示例代码多,要么... 问题总结:当我们要关闭数据库中的providers,如果在所有?
本文地址 :CodeGo.net/235632/
-------------------------------------------------------------------------------------------------------------------------
1. 根据戴安Hackborn(android工程师),没有必要在一个内容提供者关闭数据库。
在创建它的宿主进程时,内容提供者创建,并 仍然围绕只要过程做,所以没有必要 关闭数据库-它会被关闭作为内核的一部分 清理过程中的资源,当进程被kill。 感谢@bigstones指出了这一点。
2. 这个问题是有点老,但还是相当有关。请注意
CodeGo.net,如果你正在做的事情的“现代”的方式(例如使用LoaderManager和创造CursorLoaders查询在后台线程ContentProvider的),请确保你不调用db.close()在你的ContentProvider我得到各种有关CursorLoader / AsyncTaskLoader当它试图访问ContentProvider的在后台线程中,这是通过去除db.close()调用解决崩溃。 所以,如果你正在运行到崩溃,看起来像这样(果冻豆4.1.1):
或本(ICS 4.0.4):
或者,如果你看到在LogCat中看起来是这样的:
然后检查你的ContentProvider,并确保你没有关闭数据库过早。根据这一点,ContentProvider的会得到自动清理该过程时,反正杀了,所以你不需要提前关闭其数据库 这就是说,要确保你仍然正确: 关闭该从ContentProvider.query()返回的游标。 (CursorLoader /
LoaderManager这是否自动为你,但如果你正在做的LoaderManager外直接查询,或者你自定义的CursorLoader / AsyncTaskLoader子类,你必须确保你清理你的游标正常。) 您的ContentProvider以线程安全的方式。 (做到这一点最简单的方法就是确保你的数据库被包裹在一个synchronized块。)
3. 香港专业教育学院遵循Mannaz的回答,只见那
4. 如果你希望你的数据库自动关闭,您可以提供一个
如果是用SQLiteOpenHelper,可以在queryWithFactory中添加,也可以在其构造函数中添加;
下面是类:
5. 关闭它,当你用它做,最好是在finally块中,因此您可以确保它发生。我知道这听起来有点陈腐和现成的,袖口,但它是真的,我知道的唯一的答案。如果您打开数据库,并执行操作,关闭它,当你与该操作就完成了,除非你知道它会再次需要(在这种情况下,一定要关闭它一旦其不再需要的)的事实。
6. 如果你的内容的活动中providers的话,我不相信,你必须维护内容提供者的连接。你可以只管理游标对象startManagingCursor。在活动中,你可以释放内容提供商。
(你可以假设该活动的生命周期是有限的重新加载,这样就足够了。(根据ATLEAST ;))
本文标题 :关闭数据库中的ContentProvider
本文地址 :CodeGo.net/235632/
CodeGo.net,那么我会简单地调用close()方法中的onDestroy()方法,但据我所知,ContentProvider的不具有生命周期的活动做。记事本的代码似乎永远不会调用close(),所以我想它是由SQLiteOpenHelper的或其它的一块拼图处理,但我真的很想知道。我真的不示例代码多,要么... 问题总结:当我们要关闭数据库中的providers,如果在所有?
本文地址 :CodeGo.net/235632/
-------------------------------------------------------------------------------------------------------------------------
1. 根据戴安Hackborn(android工程师),没有必要在一个内容提供者关闭数据库。
在创建它的宿主进程时,内容提供者创建,并 仍然围绕只要过程做,所以没有必要 关闭数据库-它会被关闭作为内核的一部分 清理过程中的资源,当进程被kill。 感谢@bigstones指出了这一点。
2. 这个问题是有点老,但还是相当有关。请注意
CodeGo.net,如果你正在做的事情的“现代”的方式(例如使用LoaderManager和创造CursorLoaders查询在后台线程ContentProvider的),请确保你不调用db.close()在你的ContentProvider我得到各种有关CursorLoader / AsyncTaskLoader当它试图访问ContentProvider的在后台线程中,这是通过去除db.close()调用解决崩溃。 所以,如果你正在运行到崩溃,看起来像这样(果冻豆4.1.1):
Caused by: java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed. at android.database.sqlite.SQLiteConnectionPool.throwIfClosedLocked(SQLiteConnectionPool.java:962) at android.database.sqlite.SQLiteConnectionPool.waitForConnection(SQLiteConnectionPool.java:677) at android.database.sqlite.SQLiteConnectionPool.acquireConnection(SQLiteConnectionPool.java:348) at android.database.sqlite.SQLiteSession.acquireConnection(SQLiteSession.java:894) at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:834) at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62) at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:143) at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133) at android.content.ContentResolver.query(ContentResolver.java:388) at android.content.ContentResolver.query(ContentResolver.java:313) at com.hindsightlabs.paprika.loaders.GroceryListLoader.loadInBackground(GroceryListLoader.java:147) at com.hindsightlabs.paprika.loaders.GroceryListLoader.loadInBackground(GroceryListLoader.java:1) at android.support.v4.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:240) at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTask b46f Loader.java:51) at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:40) at android.support.v4.content.ModernAsyncTask$2.call(ModernAsyncTask.java:123) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) ... 4 more
或本(ICS 4.0.4):
Caused by: java.lang.IllegalStateException: database /data/data/com.hindsightlabs.paprika/databases/Paprika.db (conn# 0) already closed at android.database.sqlite.SQLiteDatabase.verifyDbIsOpen(SQLiteDatabase.java:2215) at android.database.sqlite.SQLiteDatabase.lock(SQLiteDatabase.java:436) at android.database.sqlite.SQLiteDatabase.lock(SQLiteDatabase.java:422) at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:79) at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:164) at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:156) at android.content.ContentResolver.query(ContentResolver.java:318) at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:49) at android.support.v4.content.CursorLoader.loadInBackground(CursorLoader.java:35) at android.support.v4.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:240) at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:51) at android.support.v4.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:40) at android.support.v4.content.ModernAsyncTask$2.call(ModernAsyncTask.java:123) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305) ... 4 more
或者,如果你看到在LogCat中看起来是这样的:
Cursor: invalid statement in fillWindow()
然后检查你的ContentProvider,并确保你没有关闭数据库过早。根据这一点,ContentProvider的会得到自动清理该过程时,反正杀了,所以你不需要提前关闭其数据库 这就是说,要确保你仍然正确: 关闭该从ContentProvider.query()返回的游标。 (CursorLoader /
LoaderManager这是否自动为你,但如果你正在做的LoaderManager外直接查询,或者你自定义的CursorLoader / AsyncTaskLoader子类,你必须确保你清理你的游标正常。) 您的ContentProvider以线程安全的方式。 (做到这一点最简单的方法就是确保你的数据库被包裹在一个synchronized块。)
3. 香港专业教育学院遵循Mannaz的回答,只见那
SQLiteCursor(database, driver, table, query);构造函数被弃用。然后我发现
getDatabase()它的方法,而不是
mDatabase指针,并保持构造能力lag
public class MyOpenHelper extends SQLiteOpenHelper { public static final String TAG = "MyOpenHelper"; public static final String DB_NAME = "myopenhelper.db"; public static final int DB_VESRION = 1; public MyOpenHelper(Context context) { super(context, DB_NAME, new LeaklessCursorFactory(), DB_VESRION); } //... } public class LeaklessCursor extends SQLiteCursor { static final String TAG = "LeaklessCursor"; public LeaklessCursor(SQLiteDatabase db, SQLiteCursorDriver driver, String editTable, SQLiteQuery query) { super(db, driver, editTable, query); } @Override public void close() { final SQLiteDatabase db = getDatabase(); super.close(); if (db != null) { Log.d(TAG, "Closing LeaklessCursor: " + db.getPath()); db.close(); } } } public class LeaklessCursorFactory implements CursorFactory { @Override public Cursor newCursor(SQLiteDatabase db, SQLiteCursorDriver masterQuery, String editTable, SQLiteQuery query) { return new LeaklessCursor(db,masterQuery,editTable,query); } }
4. 如果你希望你的数据库自动关闭,您可以提供一个
CursorFactory当打开它:
如果是用SQLiteOpenHelper,可以在queryWithFactory中添加,也可以在其构造函数中添加;
mContext.openOrCreateDatabase(DB_NAME, SQLiteDatabase.OPEN_READWRITE, new LeaklessCursorFactory());
下面是类:
public class LeaklessCursorFactory implements CursorFactory { @Override public Cursor newCursor(SQLiteDatabase db, SQLiteCursorDriver masterQuery, String editTable, SQLiteQuery query) { return new LeaklessCursor(db,masterQuery,editTable,query); } } public class LeaklessCursor extends SQLiteCursor { static final String TAG = "LeaklessCursor"; final SQLiteDatabase mDatabase; public LeaklessCursor(SQLiteDatabase database, SQLiteCursorDriver driver, String table, SQLiteQuery query) { super(database, driver, table, query); mDatabase = database; } @Override public void close() { Log.d(TAG, "Closing LeaklessCursor: " + mDatabase.getPath()); super.close(); if (mDatabase != null) { mDatabase.close(); } } }
5. 关闭它,当你用它做,最好是在finally块中,因此您可以确保它发生。我知道这听起来有点陈腐和现成的,袖口,但它是真的,我知道的唯一的答案。如果您打开数据库,并执行操作,关闭它,当你与该操作就完成了,除非你知道它会再次需要(在这种情况下,一定要关闭它一旦其不再需要的)的事实。
6. 如果你的内容的活动中providers的话,我不相信,你必须维护内容提供者的连接。你可以只管理游标对象startManagingCursor。在活动中,你可以释放内容提供商。
(你可以假设该活动的生命周期是有限的重新加载,这样就足够了。(根据ATLEAST ;))
本文标题 :关闭数据库中的ContentProvider
本文地址 :CodeGo.net/235632/
相关文章推荐
- Oracle的安装
- Ubuntu下Mysql常用命令详解
- ubuntu下安装mysql及卸载mysql方法
- **********MySql查询方法重要**********
- NopCommerce适应多数据库方案
- hibernate4连接mysql自动创建表之错误
- MYSQL分页limit速度太慢的优化方法
- Hibernate 中执行 对Oracle 数据库执行 save 方式是报 序列不存在 的问题?
- MySQL安全策略(MySQL安全注意事项)
- 11g新特性:SQL Management Base(SMB)
- Oracle DBA面试突击题
- mysql explain用法
- mysql多表查询1 --- 中间表
- 玩转mongodb(一):初识mongodb
- 关于sqlserver的自动生成包含数据的insert脚本问题
- SQLCipher的使用
- zabbix 监控客户端数据库 zabbix客户端
- SQL游标
- oracle服务进程和后台进程区别
- 使用Hibernate4处理Oracle XmlType字段类型