1

I have a 176,000 word SQLite database and an app that searches it (via an IntentService) and works great, never crashing. Even if thousands of "hits" are returned, the user can scroll through the list quickly and seamlessly. But I often-to-maybe-always get the Logcat warning message shown in the Title.

I've use a Cursor to access the database data and a TextView inside a ScrollView, as shown:

<ScrollView
...>
    <TextView
        android:id=                     "@+id/txaMatches"
        android:scrollbars=             "vertical"
    .../>
</ScrollView>

code:

  // initialize, etc.
  Cursor cursor = mdatabase.query(TABLE_NAME, mColumns, whereClause,
                                  wildCardReplacements, null, null, WORD_COLUMN_NAME);
  nRows = cursor.getCount();
  while (n <= prefMaxMatches && i < nRows) {
    cursor.moveToPosition(i);
    // do stuff
  }

But the warning makes me wonder if making a change in the code to get rid of it might improve responsiveness. Some searches take awhile (i.e., output not immediate, but given in a reasonable time period), depending on the Pattern entered (e.g., * must search all 176,000 words). Anyone could live with it, but we always want more speed.

What should I do? Just ignore the warning since it causes no apparent unacceptable action (e.g., crashing, slow execution)? Or what?

EDIT

Pztar suggests using LIMIT 50 in the query, but it's not entirely clear how to do so. Here's how--append LIMIT 50 to the "order by" column name (which, for me, is WORD_COLUMN_NAME):

String __whereClause = "word like ?"; 
String[] __wildCardReplacements = {pattern}; 
cursor = mdatabase.query(TABLE_NAME, mColumns, __whereClause,
                         __wildCardReplacements, null, null, 
                         WORD_COLUMN_NAME + " LIMIT 50");

--or, as better suggested by cricket_007,--

use the version of the call to query that has one more parameter:

cursor = mdatabase.query(TABLE_NAME, mColumns, __whereClause,
                         __wildCardReplacements, null, null, 
                         WORD_COLUMN_NAME, "50");
DSlomer64
  • 4,234
  • 4
  • 53
  • 88
  • So does your `listview` show all 176k words then? – Pztar May 04 '16 at 18:17
  • I don't allow all 176k words. No reason to show more than 100; 1000 max. So I just changed `preferences.xml` to allow 100,000 matches. It hung. Took several seconds to get to where I could remove it from memory. So if I did, in theory, want to allow 100,000 words, that would be a problem. So what to do about it? – DSlomer64 May 04 '16 at 18:47
  • 1
    Related: http://stackoverflow.com/questions/6361668/how-to-use-the-limit-argument-in-an-sqlite-query-with-android – OneCricketeer May 08 '16 at 17:24
  • 1
    Did you close your cursor after stuff is done? – Maxim G May 28 '16 at 21:08

1 Answers1

2

The application may run fine on your specific device or any current device but you cannot guarantee it will run on older devices. You should definitely not ignore this. The warning you're seeing is requesting more memory, on weaker devices this can cause garbage collection to run and subsequently cause unexpected results in your app.

According to your post a query can be without a pattern thus resulting in all records to be loaded. A ListView can only show an x amount of records (dependent on the device height) Let's say this number is 5 you will only ever see 5 records at a time on screen on a list of 176k. You will never see all these records at once though, so why do you load them all at once? My advice is to LIMIT your query coupled with an endless list implementation.

Change your query to LIMIT 50 meaning you will only get 50 records at a time then add this to your ListView paired with the endless list. Now every time your user scrolls and gets near the end of your current list you run the query to get the next set of 50 records and append it to your list.

Community
  • 1
  • 1
Pztar
  • 4,274
  • 6
  • 33
  • 39
  • @Pztar--This sounds like a great idea. I will get right on it. I had read about CommonsWare's `EndlessAdapter` but saw no reason to try to implement it. Now I think I do. Thanks. Another excellent product from CommonsWare. – DSlomer64 May 04 '16 at 18:51
  • It's not entirely clear how to add "LIMIT 50" to a `query`. Here's how (append `LIMIT 50` to the "order by" column name): `String __whereClause = "word like ?"; String[] __wildCardReplacements = {pattern}; cursor = mdatabase.query(TABLE_NAME, mColumns, __whereClause, __wildCardReplacements, null, null, WORD_COLUMN_NAME + " LIMIT 50");` – DSlomer64 May 04 '16 at 19:03
  • "The warning you're seeing is requesting more memory, on weaker devices this can cause garbage collection to run and subsequently cause unexpected results in your app"- No. Cursor windows are allocated in Android shared memory (ashmem). It has nothing to do with the app's heap. – Jeffrey Blattman Aug 18 '17 at 22:06