当前位置:首页 » 安卓系统 » 安卓cursorclose在哪里运行

安卓cursorclose在哪里运行

发布时间: 2022-10-01 11:06:44

❶ 如何检测 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 里面也得到应用。简化后的示例代码如下: 1import android.database.Cursor; 2import android.database.CursorWrapper; 3import android.util.Log; 4 5publicclass TestCursor extends CursorWrapper { 6privatestaticfinal String TAG = "TestCursor"; 7privateboolean mIsClosed = false; 8private Throwable mTrace; 910public TestCursor(Cursor c) { 11super(c); 12 mTrace = new Throwable("Explicit termination method 'close()' not called"); 13 } 1415 @Override 16publicvoid close() { 17 mIsClosed = true; 18 } 1920 @Override 21publicvoid finalize() throws Throwable { 22try { 23if (mIsClosed != true) { 24 Log.e(TAG, "Cursor leaks", mTrace); 25 } 26 } finally { 27super.finalize(); 28 } 29 } 30 }然后查询的时候,把 TestCursor 作为查询结果返回给 APP:1returnnew TestCursor(cursor); // cursor 是普通查询得到的结果,例如从 ContentProvider.query() 该方法同样适合于所有需要检测显式释放资源方法没有被调用的情形,是一种通用方法。但在 finalize() 方法里检测需要注意优点:准确。因为该资源在 Cursor 对象被回收时仍没被释放,肯定是发生了资源泄露。缺点:依赖于 finalize() 方法,也就依赖于 JVM 的垃圾回收策略。例如某 APP 现在有 10 个 Cursor 对象泄露,并且这 10 个对象已经不再被任何引用指向处于可回收状态,但是 JVM 可能并不会马上回收(时间不可预测),如果你现在检查不能够发现问题。另外,在某些情况下就算对象被回收 finalize() 可能也不会执行,也就是不能保证检测出所有问题。关于 finalize() 更多信息可以参考《Effective Java 2nd Edition》的 Item 7: Avoid Finalizers2. 使用方法对于APP 开发人员从GINGERBREAD 开始 Android 就提供了 StrictMode 工具协助开发人员检查是否不小心地做了一些不该有的操作。使用方法是在 Activity 里面设置 StrictMode,下面的例子是打开了检查泄漏的 SQLite 对象以及 Closeable 对象(普通 Cursor/FileInputStream 等)的功能,发现有违规情况则记录 log 并使程序强行退出。 1import android.os.StrictMode; 2 3publicclass TestActivity extends Activity { 4privatestaticfinalboolean DEVELOPER_MODE = true; 5publicvoid onCreate() { 6if (DEVELOPER_MODE) { 7 StrictMode.setVMPolicy(new StrictMode.VMPolicy.Builder() 8 .detectLeakedSqlLiteObjects() 9 .detectLeakedClosableObjects() 10 .penaltyLog() 11 .penaltyDeath() 12 .build()); 13 } 14super.onCreate(); 15 } 16 } 对于framework 开发人员如果是通过 ContentProvider 提供数据库数据,在 ContentResolver 里面已有 CloseGuard 类实行类似检测,但需要自行打开(上例也是打开 CloseGuard):1 CloseGuard.setEnabled(true);更值得推荐的办法是按照本文第一节中的检测原理,在 ContentResolver 内部类 CursorWrapperInner 里面加入。其他需要检测类似于资源泄漏的,同样可以使用该检测原理。3. 容易出错的地方忘记调用 close() 这种低级错误没什么好说的,这种应该也占不小的比例。下面说说不太明显的例子。提前返回有时候粗心会犯这种错误,在 close() 调用之前就 return 了,特别是函数比较大逻辑比较复杂时更容易犯错。这种情况可以通过把 close() 放在 finally 代码块解决1privatevoid method() { 2 Cursor cursor = query(); // 假设query() 是一个查询数据库返回 Cursor 结果的函数3if (flag == false) { //!!提前返回4return; 5 } 6 cursor.close(); 7 } 类的成员变量假设类里面有一个在类全局有效的成员变量,在方法 A 获取了查询结果,后面在其他地方又获取了一次查询结果,那么第二次查询的时候就应该先把前面一个 Cursor 对象关闭。 1publicclass TestCursor { 2private Cursor mCursor; 3 4privatevoid methodA() { 5 mCursor = query(); 6 } 7 8privatevoid 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,导致没有跑到关闭的地方:1try { 2 Cursor cursor = query(); 3// 中间省略某些出现异常的代码4 cursor.close(); 5 } catch (Exception e) { 6//!!出现异常没跑到 cursor.close()7 }这种情况应该把 close() 放到 finally 代码块里面: 1 Cursor cursor = null; 2try { 3 cursor = query(); 4// 中间省略某些出现异常的代码 5 } catch (Exception e) { 6// 出现异常 7 } finally { 8if (cursor != null) 9 cursor.close(); 10 }4. 总结思考在finalize() 里面检测是可行的,且基本可以满足需要。针对 finalize() 执行时间不确定以及可能不执行的问题,可以通过记录目前打开没关闭的 Cursor 数量来部分解决,超过一定数目发出警告,两种手段相结合。还有没有其他检测办法呢?有,在 Cursor 构造方法以及 close() 方法添加 log,运行一段时间后检查 log 看哪个地方没有关闭。简化代码如下: 1import android.database.Cursor; 2import android.database.CursorWrapper; 3import android.util.Log; 4 5publicclass TestCursor extends CursorWrapper { 6privatestaticfinal String TAG = "TestCursor"; 7private Throwable mTrace; 8 9public TestCursor(Cursor c) { 10super(c); 11 mTrace = new Throwable("cusor opened here"); 12 Log.d(TAG, "Cursor " + this.hashCode() + " opened, stacktrace is: ", mTrace); 13 } 1415 @Override 16publicvoid close() { 17 mIsClosed = true; 18 Log.d(TAG, "Cursor " + this.hashCode() + " closed."); 19 } 20 }检查时看某个 hashCode() 的 Cursor 有没有调用过 close() 方法,没有的话说明资源有泄露。这种方法优点是同样准确,且更可靠。

❷ 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都关闭

❸ 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 里面也得到应用。简化后的示例代码如下:import android.database.Cursor; import android.database.CursorWrapper; import android.util.Log; public class TestCursor extends CursorWrapper { private static final String TAG = "TestCursor"; private boolean mIsClosed = false; private Throwable mTrace; public TestCursor(Cursor c) { super(c); mTrace = new Throwable("Explicit termination method 'close()' not called"); } @Override public void close() { mIsClosed = true; } @Override public void finalize() throws Throwable { try { if (mIsClosed != true) { Log.e(TAG, "Cursor leaks", mTrace); } } finally { super.finalize(); } } }然后查询的时候,把 TestCursor 作为查询结果返回给 APP: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 Finalizers2. 使用方法对于APP 开发人员从GINGERBREAD 开始 Android 就提供了 StrictMode 工具协助开发人员检查是否不小心地做了一些不该有的操作。使用方法是在 Activity 里面设置 StrictMode,下面的例子是打开了检查泄漏的 SQLite 对象以及 Closeable 对象(普通 Cursor/FileInputStream 等)的功能,发现有违规情况则记录 log 并使程序强行退出。import android.os.StrictMode; public class TestActivity extends Activity { private static final boolean DEVELOPER_MODE = true; public void onCreate() { if (DEVELOPER_MODE) { StrictMode.setVMPolicy(new StrictMode.VMPolicy.Builder() .detectLeakedSqlLiteObjects() .detectLeakedClosableObjects() .penaltyLog() .penaltyDeath() .build()); } super.onCreate(); } }对于framework 开发人员如果是通过 ContentProvider 提供数据库数据,在 ContentResolver 里面已有 CloseGuard 类实行类似检测,但需要自行打开(上例也是打开 CloseGuard):CloseGuard.setEnabled(true);更值得推荐的办法是按照本文第一节中的检测原理,在 ContentResolver 内部类 CursorWrapperInner 里面加入。其他需要检测类似于资源泄漏的,同样可以使用该检测原理。3. 容易出错的地方忘记调用 close() 这种低级错误没什么好说的,这种应该也占不小的比例。下面说说不太明显的例子。提前返回有时候粗心会犯这种错误,在 close() 调用之前就 return 了,特别是函数比较大逻辑比较复杂时更容易犯错。这种情况可以通过把 close() 放在 finally 代码块解决。private void method() { Cursor cursor = query(); // 假设 query() 是一个查询数据库返回 Cursor 结果的函数 if (flag == false) { // !!提前返回 return; } cursor.close(); }类的成员变量假设类里面有一个在类全局有效的成员变量,在方法 A 获取了查询结果,后面在其他地方又获取了一次查询结果,那么第二次查询的时候就应该先把前面一个 Cursor 对象关闭。public class TestCursor { private Cursor mCursor; private void methodA() { mCursor = query(); } private void methodB() { // !!必须先关闭上一个 cursor 对象 mCursor = query(); } }注意:曾经遇到过有人对 mCursor 感到疑惑,明明是同一个变量为什么还需要先关闭?首先 mCursor 是一个 Cursor 对象的引用,在 methodA 时 mCursor 指向了 query() 返回的一个 Cursor 对象 1;在 methodB() 时它又指向了返回的另外一个 Cursor 对象 2。在指向 Cursor 对象 2 之前必须先关闭 Cursor 对象 1,否则就出现了 Cursor 对象 1 在 finalize() 之前没有调用 close() 的情况。异常处理打开和关闭 Cursor 之间的代码出现 exception,导致没有跑到关闭的地方:try { Cursor cursor = query(); // 中间省略某些出现异常的代码 cursor.close(); } catch (Exception e) { // !!出现异常没跑到 cursor.close() }这种情况应该把 close() 放到 finally 代码块里面:Cursor cursor = null; try { cursor = query(); // 中间省略某些出现异常的代码 } catch (Exception e) { // 出现异常 } finally { if (cursor != null) cursor.close(); }4. 总结思考在finalize() 里面检测是可行的,且基本可以满足需要。针对 finalize() 执行时间不确定以及可能不执行的问题,可以通过记录目前打开没关闭的 Cursor 数量来部分解决,超过一定数目发出警告,两种手段相结合。还有没有其他检测办法呢?有,在 Cursor 构造方法以及 close() 方法添加 log,运行一段时间后检查 log 看哪个地方没有关闭。简化代码如下:import android.database.Cursor; import android.database.CursorWrapper; import android.util.Log; public class TestCursor extends CursorWrapper { private static final String TAG = "TestCursor"; private Throwable mTrace; public TestCursor(Cursor c) { super(c); mTrace = new Throwable("cusor opened here"); Log.d(TAG, "Cursor " + this.hashCode() + " opened, stacktrace is: ", mTrace); } @Override public void close() { mIsClosed = true; Log.d(TAG, "Cursor " + this.hashCode() + " closed."); } }检查时看某个 hashCode() 的 Cursor 有没有调用过 close() 方法,没有的话说明资源有泄露。这种方法优点是同样准确,且更可靠。

❹ android中怎么将SQLite中的数据显示在Listview中(用Cursor)

public List<String> findAllDate(){//我的一个方法
List<String> list = new ArrayList<String>();
SQLiteDatabase database = dbopenhelper.getWritableDatabase();
Cursor cursor = database.rawQuery("select date from health", new String[]{});//这边写上你的查询语句
while(cursor.moveToNext()){
list.add(cursor.getString(0));
}
cursor.close();
database.close();
return list;
}
之后就是把这个LIST显示在Listview中;
如:SimpleAdapter adapter=new SimpleAdapter(Listview.this,list
,R.layout.viewdate,new String[]{"date"},
new int[]{R.id.tdate});
listview.setAdapter(adapter);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() { //事件
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long arg3) {
....
}

});
希望对你有用

❺ android 下使用Cursor如何获得专辑图片

android下使用cursor获取专辑图片,主要是在数据库里面先保存专辑图片的url地址,当使用cursor游标遍历数据库数据的时候,使用资源操作类进行加载相应的url,如下代码:
Cursor cursor = context.getContentResolver().query(Media.EXTERNAL_CONTENT_URI, columns, null, null, null);
Log.e("cursor" , (cursor==null) + "");
while(cursor.moveToNext()) {
// 查找封面图片
long albumId = cursor.getLong(5);
// 读取专辑图片
String album_uri = "content://media/external/audio/albumart"; // 专辑Uri对应的字符串
Uri albumUri = ContentUris.withAppendedId(Uri.parse(album_uri), albumId);
// 取图片 ==> 得到一个输入流
Bitmap coverPhoto = null ;
try {
InputStream is = context.getContentResolver().openInputStream(albumUri);
if(null != is) {
coverPhoto = BitmapFactory.decodeStream(is);
}
} catch (Exception e) {
e.printStackTrace();
}
data.add(new Audio(cursor.getLong(0), cursor.getString(1) , cursor.getString(2) , cursor.getLong(3) , cursor.getString(4) , albumId , coverPhoto));
}
cursor.close();

❻ android数据库怎么样把Cursor的值 赋值给字符串

  • 调用cursor的getString方法(参考代码见下面)

    在while循环里,如果cursor.moveToNext()能移动到下一条

    就代表游标对象里有数据。然后调用cursor的getString()方法把cursor的复制给字符串。

  • publicList<BlackBean>findAll(){
    SQLiteDatabasedb=helper.getReadableDatabase();
    List<BlackBean>blackBeans=newArrayList<BlackBean>();
    Cursorcursor=db.query("blackNumber",newString[]{"number","mode"},null,null,null,null,null);
    while(cursor.moveToNext()){
    BlackBeanblackNumberInfo=newBlackBean();
    blackNumberInfo.setNumber(cursor.getString(0));
    blackNumberInfo.setMode(cursor.getString(1));
    blackBeans.add(blackNumberInfo);
    }
    cursor.close();
    returnblackBeans;
    }

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

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

❽ 使用游标的基本步骤是什么

游标(cursor)是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果。每个游标区都有一个名字,用户可以用SQL语句逐一从游标中获取记录,并赋给主变量,交由主语言进一步处理。
create proc cursorTest
@_id int=0,
@_name varchar(50)=''
as--创建游标
declare @cursor cursor--设定游标欲操作的数据集
set @cursor=cursor for
select _id,_name from users
open @cursor--打开游标
fetch next from @cursor into @_id,@_name--移动游标指向到第一条数据,提取第一条数据存放在变量中
while(@@fetch_status=0)begin--如果上一次操作成功则继续循环
print @_name--操作提出的数据
fetch next from @cursor into @_id,@_name--继续提下一行
end
close @cursor--关闭游标
deallocate @cursor--删除游标

热点内容
明日之后电脑配置如何提高 发布:2025-03-15 02:08:39 浏览:861
c阶乘算法 发布:2025-03-15 02:08:39 浏览:363
挂锁忘记密码有什么办法 发布:2025-03-15 02:04:45 浏览:407
sql模糊查找 发布:2025-03-15 02:04:06 浏览:753
服务器如何不让玩家搞破坏 发布:2025-03-15 02:04:02 浏览:57
nmake编译win32 发布:2025-03-15 01:58:27 浏览:164
50台电脑网咖服务器 发布:2025-03-15 01:51:50 浏览:781
linux内核页表 发布:2025-03-15 01:48:53 浏览:390
为什么安卓手机短信每天都在收发 发布:2025-03-15 01:48:17 浏览:974
ftp辅助 发布:2025-03-15 01:41:52 浏览:317