导航:首页 > 操作系统 > androidcursor关闭

androidcursor关闭

发布时间:2023-03-17 00:02:36

A. android中Cursor用完之后有必要关闭吗

把能关的资源关掉是一个好习惯,可以提高程序的性能

B. android在异步任务中如何关闭Cursor

在我们开发应用的时候,很多时候会遇到这种问题。 查询数据会比较耗时,所以我们想把查询数据放在一个异步任务中,查询结果获得Cursor,然轮拍后在onPostExecute (Cursor result)方法中设置Adapter,我们可能会想到使用Activity的managedQuery来生成Cursor,这样Cursor就会与Acitivity的生命周期一致了,多么完美的解决方法!然而事实上managedQuery也有很大的局限性,managedQuery生成的Cursor必须确保不会被替换,因为可腊档羡能很多程序事实上查询条件都是不确定的,因此我们经常会用新查询的Cursor来替换掉原先的Cursor。因此这种方法适用范围也是很小。 我们不能直接蠢则将Cursor关闭掉,但是注意,CursorAdapter在Acivity结束时并没有自动的将Cursor关闭掉,因此,你需要在onDestroy函数中,手动关闭。 @Overrideprotected void onDestroy() { super.onDestroy(); mPhotoLoader.stop(); if(mAdapter != null && mAdapter.getCursor() != null) { mAdapter.getCursor().close();}} 如果没有在Adapter中用到Cursor,可以手动关闭Cursor。 1Cursor cursor =null;2try{3cursor = mContext.getContentResolver().query(uri, null, null,null,

C. android SQLiteDatabase Cursor需要关闭不

cursor.close就可以关闭 sqlitedatabase不需要关闭 ,你可以拆芹袭把sqlitedatabase预先建好,要用旅兄时就拿来用,不需首腔要每次都新建。

D. android 当cursor为null 用不用关闭

如果已经crusor为null,是不用关闭的,因为已经不占据资源了,会被回收掉

E. 如何检测 Android Cursor 泄漏

简介:
本文介绍如何在 Android 检测 Cursor 泄漏的原理以及使用方法,还指出几种常见的出错示例。有一些泄漏在代码中难以察觉,但程序长时间运行后必然会出现异常。同时该方法同样适合于其他需要检测资源泄露的情况。

最近发现某蔬菜手机连接程序在查询媒体存储(MediaProvider)数据库时出现严重 Cursor 泄漏现象,运行一段时间后会导致系统中所有使用到该数据库的程序无法使用。另外在工作中也常发现有些应用有 Cursor 泄漏现象,由于需要长时间运行才会出现异常,所以有的此类 bug 很长时间都没被发现。
但是一旦 Cursor 泄漏累计到一定数目(通常为数百个)必然会出现无法查询数据库的情况,只有等数据库服务所在进程死掉重启才能恢复正常。通常的出错信息如下,指出某 pid 的程序打开了 866 个 Cursor 没有关闭,导致了 exception:
3634 3644 E javaBinder: *** Uncaught remote exception! (Exceptions are not yet supported across processes.)
3634 3644 E JavaBinder: android.database.: Cursor window allocation of 2048 kb failed. # Open Cursors=866 (# cursors opened by pid 1565=866)
3634 3644 E JavaBinder: at android.database.CursorWindow.(CursorWindow.java:104)
3634 3644 E JavaBinder: at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198)
3634 3644 E JavaBinder: at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:147)
3634 3644 E JavaBinder: at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:141)
3634 3644 E JavaBinder: at android.database.CursorToBulkCursorAdaptor.getBulkCursorDescriptor(CursorToBulkCursorAdaptor.java:143)
3634 3644 E JavaBinder: at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:118)
3634 3644 E JavaBinder: at android.os.Binder.execTransact(Binder.java:367)
3634 3644 E JavaBinder: at dalvik.system.NativeStart.run(Native Method)

1. Cursor 检测原理
在 Cursor 对象被 JVM 回收运行到 finalize() 方法的时候,检测 close() 方法有没有被调用,此办法在 ContentResolver 里面也得到应用。简化后的示例代码如下:
1 import android.database.Cursor;
2 import android.database.CursorWrapper;
3 import android.util.Log;
4
5 public class TestCursor extends CursorWrapper {
6 private static final String TAG = "TestCursor";
7 private boolean mIsClosed = false;
8 private Throwable mTrace;
9
10 public TestCursor(Cursor c) {
11 super(c);
12 mTrace = new Throwable("Explicit termination method 'close()' not called");
13 }
14
15 @Override
16 public void close() {
17 mIsClosed = true;
18 }
19
20 @Override
21 public void finalize() throws Throwable {
22 try {
23 if (mIsClosed != true) {
24 Log.e(TAG, "Cursor leaks", mTrace);
25 }
26 } finally {
27 super.finalize();
28 }
29 }
30 }

然后查询的时候,把 TestCursor 作为查询结果返回给 APP:
1 return new TestCursor(cursor); // cursor 是普通查询得到的结果,例如从 ContentProvider.query()

该方法同样适合于所有需要检测显式释放资源方法没有被调用的情形,是一种通用方法。但在 finalize() 方法里检测需要注意
优点:准确。因为该资源在 Cursor 对象被回收时仍没被释放,肯定是发生了资源泄露。
缺点:依赖于 finalize() 方法,也就依赖于 JVM 的垃圾回收策略。例如某 APP 现在有 10 个 Cursor 对象泄露,并且这 10 个对象已经不再被任何引用指向处于可回收状态,但是 JVM 可能并不会马上回收(时间不可预测),如果你现在检查不能够发现问题。另外,在某些情况下就算对象被回收 finalize() 可能也不会执行,也就是不能保证检测出所有问题。关于 finalize() 更多信息可以参考《Effective Java 2nd Edition》的 Item 7: Avoid Finalizers
2. 使用方法
对于 APP 开发人员
从 GINGERBREAD 开始 Android 就提供了 StrictMode 工具协助开发人员检查是否不小心地做了一些不该有的操作。使用方法是在 Activity 里面设置 StrictMode,下面的例子是打开了检查泄漏的 SQLite 对象以及 Closeable 对象(普通 Cursor/FileInputStream 等)的功能,发现有违规情况则记录 log 并使程序强行退出。
1 import android.os.StrictMode;
2
3 public class TestActivity extends Activity {
4 private static final boolean DEVELOPER_MODE = true;
5 public void onCreate() {
6 if (DEVELOPER_MODE) {
7 StrictMode.setVMPolicy(new StrictMode.VMPolicy.Builder()
8 .detectLeakedSqlLiteObjects()
9 .detectLeakedClosableObjects()
10 .penaltyLog()
11 .penaltyDeath()
12 .build());
13 }
14 super.onCreate();
15 }
16 }

对于 framework 开发人员
如果是通过 ContentProvider 提供数据库数据,在 ContentResolver 里面已有 CloseGuard 类实行类似检测,但需要自行打开(上例也是打开 CloseGuard):
1 CloseGuard.setEnabled(true);

更值得推荐的办法是按照本文第一节中的检测原理,在 ContentResolver 内部类 CursorWrapperInner 里面加入。其他需要检测类似于资源泄漏的,同样可以使用该检测原理。
3. 容易出错的地方
忘记调用 close() 这种低级错误没什么好说的,这种应该也占不小的比例。下面说说不太明显的例子。
提前返回
有时候粗心会犯这种错误,在 close() 调用之前就 return 了,特别是函数比较大逻辑比较复杂时更容易犯错。这种情况可以通过把 close() 放在 finally 代码块解决
1 private void method() {
2 Cursor cursor = query(); // 假设 query() 是一个查询数据库返回 Cursor 结果的函数
3 if (flag == false) { // !!提前返回
4 return;
5 }
6 cursor.close();
7 }

类的成员变量
假设类里面有一个在类全局有效的成员变量,在方法 A 获取了查询结果,后面在其他地方又获取了一次查询结果,那么第二次查询的时候就应该先把前面一个 Cursor 对象关闭。
1 public class TestCursor {
2 private Cursor mCursor;
3
4 private void methodA() {
5 mCursor = query();
6 }
7
8 private void methodB() {
9 // !!必须先关闭上一个 cursor 对象
10 mCursor = query();
11 }
12 }

注意:曾经遇到过有人对 mCursor 感到疑惑,明明是同一个变量为什么还需要先关闭?首先 mCursor 是一个 Cursor 对象的引用,在 methodA 时 mCursor 指向了 query() 返回的一个 Cursor 对象 1;在 methodB() 时它又指向了返回的另外一个 Cursor 对象 2。在指向 Cursor 对象 2 之前必须先关闭 Cursor 对象 1,否则就出现了 Cursor 对象 1 在 finalize() 之前没有调用 close() 的情况。
异常处理
打开和关闭 Cursor 之间的代码出现 exception,导致没有跑到关闭的地方:
1 try {
2 Cursor cursor = query();
3 // 中间省略某些出现异常的代码
4 cursor.close();
5 } catch (Exception e) {
6 // !!出现异常没跑到 cursor.close()
7 }

这种情况应该把 close() 放到 finally 代码块里面:
1 Cursor cursor = null;
2 try {
3 cursor = query();
4 // 中间省略某些出现异常的代码
5 } catch (Exception e) {
6 // 出现异常
7 } finally {
8 if (cursor != null)
9 cursor.close();
10 }

F. Android Cursor(光标)解析

SQLiteDatabase db = dataBaseHelper.getWritableDatabase();
Cursor cursor = db.rawQuery("select *from User",null);
1.光标的行数:int getCount()

2.当前光标的位置:int getPosition()
返回的值从零开始, 当第一次返回行集时游标将位于位置 -1,即第一行之前。在返回最后一行之后,对 next() 的另一个调用将使光标离开最后一个条目,位于 count() 的位置。

3.从当前位置应用的偏移量:boolean move(int offset)
将光标从当前位置向前或向后移动一个相对量。 正偏移向前移动,负偏移向后移动。 如果最终位置在结果集的边界之外,则结果位置将分别固定为 -1 或 count(),具体取决于该值是在集合的前端还是末尾。如果请求的目的地可达,此方法将返回 true,否则返回 false。

4.将光标移动到绝对位置:boolean moveToPosition(int position)
值的有效范围是 -1 <= 位置 <= 计数。如果请求目的地可达,此方法将返回 true,否则返回 false。

5.将光标移动到第一行:boolean moveToFirst()

6.将光标移动到最后一行:boolean moveToLast()

7.将光标移动到下一行:boolean moveToNext()

8.将光标移动到上一行:boolean moveToPrevious()

9.返回光标是否指向第一行:boolean isFirst()

10.返回光标是否指向最后一行:boolean isLast()

11.返回光标是否指向第一行之前的位置:boolean isBeforeFirst()

12.返回光标是否指向最后一行之后的位置:boolean isAfterLast()

13.给定列名的从零开始的列索引,如果列名不存在,则返回 -1:int getColumnIndex(String columnName)

14.给定列名的从零开始的索引,如果该列不存在则抛出非法参数异常:int getColumnIndexOrThrow(String columnName) throws IllegalArgumentException

15.给定的从零开始的列索引处的列名:String getColumnName(int columnIndex)

16.返回一个字符串数组,其中按列在结果中的顺序保存结果集中所有列的名称。:String[] getColumnNames()

17.返回总列数:int getColumnCount()

18.各类型返回值
(1)以字节数组的形式返回请求列的值:byte[] getBlob(int columnIndex)
(2)以字符串形式返回请求列的值:String getString(int columnIndex)
(3)以整数形式返回请求列的值:int getInt(int columnIndex)
(4)以 long 形式返回请求列的值:long getLong(int columnIndex)
(5)以浮点数形式返回请求列的值:float getFloat(int columnIndex)
(6)以双精度形式返回请求列的值:double getDouble(int columnIndex)
(7)返回给定列值的数据类型:int getType(int columnIndex)
(8)列值是否为空:boolean isNull(int columnIndex)
(9)以短形式返回请求列的值:short getShort(int columnIndex)

19.检索请求的列文本并将其存储在提供的缓冲区中:void StringToBuffer(int columnIndex, CharArrayBuffer buffer)

20.关闭游标:void close()

21.游标是否关闭:boolean isClosed()

22.注册一个观察者,当支持此游标的内容发生变化时调用该观察者:void registerContentObserver(ContentObserver observer)

23.销毁注册的观察者:void unregisterContentObserver(ContentObserver observer)

24.注册一个观察者,当数据集的内容发生变化时被调用:void registerDataSetObserver(DataSetObserver observer)

25.销毁注册的观察者:void unregisterDataSetObserver(DataSetObserver observer)

26.注册以查看内容 URI 的更改。这可以是特定数据行的 URI,也可以是内容类型的通用URI:void setNotificationUri(ContentResolver cr, Uri uri)

cr是上下文,uri是需要观看的内容
27.是否所有光标移动都应导致调用 onMove():boolean getWantsAllOnMoveCalls()

只有在此方法返回 true 时,才会跨进程调用 onMove()
28.返回一组额外的值:Bundle getExtras()

29.光标用户与光标通信的带外方式:Bundle respond(Bundle extras)
30.设置 Bundle 返回的getExtras():void setExtras(Bundle extras)

G. android cursor finalized without prior close 怎么查

[java] view plain
Cursor循环内再申请Cursor,记得将内部申请的每个Cursor都加上close
[java] view plain
ContentResolver resolver = getContentResolver();
Uri URI = ContactsContract.Contacts.CONTENT_URI;
String[] columns = new String[] {ContactsContract.Contacts._ID
,PhoneLookup.DISPLAY_NAME};
//查询联系人ID和联系人名称两列

Cursor cursor = resolver.query(URI, columns,
PhoneLookup.HAS_PHONE_NUMBER+"=1", null, null);
//限定只返回有号码的联系人

while(cursor.moveToNext()){

String phoneNum="";
Cursor cursor2=resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI
, new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER},
ContactsContract.CommonDataKinds.Phone.CONTACT_ID+"="+cursor.getLong(0)
, null, null);
//因为号茄唤码与联系人不存在一个表中,一个联系人可能存在多个号码,
//所以根据联系人ID查找号码,存在phoneNum中

while(cursor2.moveToNext()) {
phoneNum+=cursor2.getString(0)+"||";
//循环把该联系的所属的号码加进phoneNum
}
cursor2.close();
//同学,就是这腊芹里了,cursor里申请第二个cursor2,
//记得将每个cursor2给关闭了,不然就资源泄漏了。

Log.d("LocTestDemo", "--" + cursor.getLong(0) + "颤局凯:"
+ cursor.getString(1) + "::" + phoneNum);

//往JSONArray里添加一个联系人信息
singer = new JSONObject();
try {
singer.put("id", cursor.getLong(0));
singer.put("name", cursor.getString(1));
singer.put("phone", phoneNum);
} catch (JSONException e) {
e.printStackTrace();
}
singers.put(singer);

}
cursor.close();
//这里其实还得加上try,里外的Cursor都要加,
//在catch里判断cursor是否为空,不为空还得给关闭。

cursor循环内再申请cursor记得将内部申请的每个cursor都关闭

H. android cursor is deactivated prior to calling this method.怎么回事

此异常由明衫卖于app在使用已经关闭的cursor,可以按照如下方法修改解决:
修改packages/apps/Browser/src/com/android/browser/BrowserSnapshotPage.java
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Cursor c = mAdapter.getItem(position);
String title = c.getString(SNAPSHOT_TITLE);
String url = "file://" + c.getString(SNAPSHOT_VIEWSTATE_PATH);
--删除这一行 c.close();
mCallback.openSnapshot(id, title, url);
}
因为我们之前并不是打开一个激逗cursor,所以这儿不需要关闭塌改。

I. android数据库每次查询完都要关闭吗

关于数宏派据库句柄,每次用完是必须手首脊动调用close()方法关掉的;关于cursor一般情况也是要求关掉的,如果只获取了一次结果集,不关掉cursor对程序的逻辑没有影响,只是会抛一个非必要蔽芹贺性异常,但是如果多次获取结果集,就必须先关掉cursor,再重新获取结果集,否则cursor没释放,之后的结果集是获取不到的,且会报错。所以,总的来说,都要关掉。

阅读全文

与androidcursor关闭相关的资料

热点内容
微信聊天界面源码 浏览:24
seo竞价推广点击价格算法公式 浏览:319
框架结构可以加密吗 浏览:218
python编译器怎么清除 浏览:73
linux全局socks代理 浏览:611
php微信抽奖 浏览:771
压缩算法嵌入式移植 浏览:531
php新手小例子 浏览:233
按照医生的算法一周是几天 浏览:805
三次b样条曲线算法 浏览:924
java7特性 浏览:555
爱山东app小学报名怎么知道报没报上 浏览:458
android获取wifi信号 浏览:133
娜拉美妆app怎么使用 浏览:760
有了源码要买服务器吗 浏览:365
app怎么查看自己的存款利息 浏览:515
碧蓝安卓与b站有什么区别 浏览:342
php静态块 浏览:719
ftpmget命令 浏览:475
源码时代怎样 浏览:415