简体   繁体   English

关于Android中SQLite数据库游标的几个问题

[英]A few questions about SQLite database cursors in Android

To implement database access in my application I followed Lars Vogel tutorial , but I'm very confused about a couple of things... 为了在我的应用程序中实现数据库访问,我遵循了Lars Vogel教程 ,但我对一些事情感到很困惑......

1) Every time a call is made to fetchTodo a new cursor will be created and returned. 1)每次调用fetchTodo都会创建并返回一个新游标。 Leaving the previous cursor for the garbage collector. 将前一个光标留给垃圾收集器。 So, if I don't use startManagingCursor or even the CursorLoader for that matter, should I call a .close() on the cursor when I'm done with it ? 所以,如果我不使用startManagingCursor甚至CursorLoader那么,当我完成它时,我应该在光标上调用.close()吗? Outside of fetchTodo scope of course, example: 当然,在fetchTodo范围之外,例如:

Cursor cursor = mNotesAdapter.fetchTodo();
// do something...
cursor.close();

I'm done with this cursor and new one will be created on the next fetch, should I close it like this then or should I leave it for the garbage collector? 我已经完成了这个游标,并且将在下一次获取时创建新游标,如果我这样关闭它还是应该将它留给垃圾收集器? Although I think I'm talking about 2 things entirely different... Point being, should I close it like in the example above or not? 虽然我认为我在谈论两件完全不同的事情......重点是,我应该像上面的例子那样关闭它吗?

2) Cursor also has a .deactivate() method and the documentation says it uses less resources (than active cursors). 2) Cursor也有一个.deactivate()方法,文档说它使用的资源较少(比活动游标)。 When exactly should I use this? 我什么时候应该使用它? For instance, in my app, I have a ListActivity which is populated through a SimpleCursorAdapter (the code initialization for this is only called once). 例如,在我的应用程序中,我有一个ListActivity ,它通过SimpleCursorAdapter填充(代码初始化只调用一次)。 The cursor being used is a class member variable, because I need it outside the method that populates the list. 正在使用的游标是一个类成员变量,因为我需要在填充列表的方法之外。 I need it to requery the database when something is deleted from it. 当从中删除某些内容时,我需要它来重新查询数据库。 But until a record is deleted, which is a user action and may take a while to happen, should I deactivate the cursor in the meantime? 但是,除非删除记录,这是用户操作并且可能需要一段时间才会发生,我应该在此期间停用光标吗? Cause it will be active again when I call .requery() again. 因为当我再次调用.requery()时它会再次激活。 Or the SimpleCursorAdapter is going to stop working because the cursor is not active? 或者SimpleCursorAdapter将停止工作,因为光标不活动?

EDIT: I just tested this one and found out that I can't call deactivate() after setting up the cursor adapter. 编辑:我刚测试了这个,发现在设置游标适配器后我无法调用deactivate() The list will be empty if the cursor is not active, so it needs to remain active for as long as the ListActivity is displayed. 如果光标未激活,则列表将为空,因此只要显示ListActivity,它就需要保持活动状态。 In the end, we should just let StartManagingCursor handle it then. 最后,我们应该让StartManagingCursor处理它。 Or the new CursorLoader . 或者新的CursorLoader

3) I know that startManagingCursor / stopManagingCursor are deprecated but I'm not targeting Honeycomb (at least for the time being) and I don't want to deal with the new CursorLoader for now. 3)我知道startManagingCursor / stopManagingCursor已被弃用,但我不是针对Honeycomb(至少目前stopManagingCursor ),我现在不想处理新的CursorLoader But in the tutorial above, startManagingCursor is used everywhere, but stopManagingCursor is never called once. 但是在上面的教程中, startManagingCursor在任何地方都使用,但是stopManagingCursor永远不会被调用一次。 Why not? 为什么不? Does Android deals with that in it's own way? Android会以自己的方式处理吗? Any situation I should call stopManagingCursor ? 我应该调用stopManagingCursor任何情况?

Edit: Updated answer to reflect updated question 1: 编辑:更新的答案以反映更新的问题1:

1) Every time a call is made to fetchTodo a new cursor will be created and returned. 1)每次调用fetchTodo时,都会创建并返回一个新游标。 Leaving the previous cursor for the garbage collector. 将前一个光标留给垃圾收集器。 So, if I don't use startManagingCursor or even the CursorLoader for that matter, should I call a .close() on the cursor when I'm done with it ? 所以,如果我不使用startManagingCursor甚至CursorLoader那么,当我完成它时,我应该在光标上调用.close()吗?

Yes, you should definitely either tell Android to startManagingCursor() , use LoaderManager / CursorLoader or close() it yourself. 是的,你绝对应该告诉Android startManagingCursor() ,使用LoaderManager / CursorLoader或者自己close() Not doing so will leak memory, the GC won't help with that as there's native resources behind the Cursor (eg file handles to the database). 不这样做会泄漏内存,GC将无法帮助,因为Cursor背后有本机资源(例如数据库的文件句柄)。

2) Cursor also has a .deactive() method and the documentation says it uses less resources (than active cursors). 2)Cursor也有一个.deactive()方法,文档说它使用的资源更少(比活动游标)。 When exactly should I use this? 我什么时候应该使用它? ... ...

EDIT to other readers: The OP found an answer and posted it in his question. 编辑给其他读者:OP找到答案并在他的问题中发布。 The following still holds: 以下仍然适用:

I've never used deactivate() (there's no deactive() ), maybe someone else can explain this. 我从来没有使用过deactivate() (没有deactive() ),也许其他人可以解释这个。 If you want really painless requery/updates, do check out the LoaderManager framework -- it's not only for Honeycomb: using the compat library you can use LoaderManager (and Fragments ) down to Android 1.6. 如果你想要真正无痛的重新查询/更新,请查看LoaderManager框架 - 它不仅适用于Honeycomb:使用compat库你可以使用LoaderManager (和Fragments )到Android 1.6。 Not only is it less code for you to write, but it completely offloads these things to Android, much more so than startManagingCursor() . 它不仅减少了你编写的代码,而且完全将这些东西卸载到Android上,远远超过了startManagingCursor()

EDIT2: Some notes on LoaderManager EDIT2:关于LoaderManager一些注意事项

There are LoaderManager tutorials on developer.android.com but these are quite... complex and hard to understand the first time like most of the tutorials there. developer.android.com上有LoaderManager教程,但是这些教程非常复杂且难以理解,就像大多数教程一样。 I also had to dig a lot, the best all-in-one stop I found so far is http://mobile.tutsplus.com/tutorials/android/android-sdk_loading-data_cursorloader/ (plus all the javadocs and compat lib source you can find) --- the way LoaderManager works is very similar to the (now also deprecated, replaced by DialogFragment ) managed dialogs with their onCreateDialog , onPrepareDialog methods where you just tell Android to "show dialog #123" and then Android calls your code with that ID; 我也不得不深入挖掘,到目前为止我发现的最好的一体化停止是http://mobile.tutsplus.com/tutorials/android/android-sdk_loading-data_cursorloader/ (以及所有的javadoc和compat lib源码)你可以找到)--- LoaderManager工作方式非常类似于(现在也被弃用,取而代之的是DialogFragment )托管对话框及其onCreateDialogonPrepareDialog方法,你只需告诉Android“显示对话框#123”然后Android调用你的具有该ID的代码; same for loaders: "load loader #123", Android calls on onCreateLoader() . 同样适用于加载器:“load loader#123”,Android调用onCreateLoader()

The only obvious drawback is initially, that LoaderManager relies heavily on the ContentProvider framework and some people seem to really dislike that. 唯一明显的缺点是,最初, LoaderManager严重依赖于ContentProvider框架,有些人似乎真的不喜欢它。 Sure, it's additional learning and code, but once you have a ContentProvider for your own data (even if only used privately in your app), all the data-to-view bindng is a breeze with CursorLoader . 当然,它是额外的学习和代码,但是一旦你拥有了一个ContentProvider用于你自己的数据(即使只在你的应用程序中私下使用),所有数据到视图的绑定都是轻而易举的CursorLoader IMHO, there's little difference between rolling your own "content provider" and actually implementing the ContentProvider -- but this is just my highly controversial opinion :) 恕我直言,滚动你自己的“内容提供者”和实际实现ContentProvider之间没有什么区别 - 但这只是我极具争议的意见:)

3) I know that startManagingCursor/stopManagingCursor are deprecated but I'm not targeting Honeycomb (at least for the time being) and I don't want to deal with the new CursorLoader for now. 3)我知道startManagingCursor / stopManagingCursor已被弃用,但我不是针对Honeycomb(至少目前为止),我现在不想处理新的CursorLoader。 But in the tutorial above, startManagingCursor is used everywhere, but stopManagingCursor is never called once. 但是在上面的教程中,startManagingCursor在任何地方都使用,但是stopManagingCursor永远不会被调用一次。 Why not? 为什么不? Does Android deals with that in it's own way? Android会以自己的方式处理吗? Any situation I should call stopManagingCursor? 我应该调用stopManagingCursor的任何情况?

Once you call startManagingCursor() the Cursor is no longer your problem. 一旦调用startManagingCursor()Cursor就不再是你的问题了。 Android will take care of closing the Cursor when your Activity gets destroyed (user navigates away, orientation change, ...). 当您的Activity被销毁(用户导航,方向更改,......)时,Android将负责关闭Cursor。 There's no need to match a call to startManagingCursor() with a call to stopManagingCursor() -- you usually don't want to take on the burden of managing a Cursor again once you've gotten rid of it. 没有必要stopManagingCursor() startManagingCursor()的调用与对stopManagingCursor()的调用相stopManagingCursor() - 一旦你摆脱了它,你通常不想承担再次管理Cursor的负担。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM