Android adapter with section headings: performance problems - android

I have a custom adapter to display a list of items with section headings. I've looked at Jeff Sharkey's SeparatedListAdapter and CommonsWare's MergeAdapter as examples of how to achieve this, and I now have a solution which works by providing a separate adapter for the content of each section.
This creates a big performance problem, though. In my case, there are potentially thousands of items in the list, each with an associated date, and I want to use the date as section heading for all the items with that date.
So, without section headings, I'd have a single Cursor which returns the items sorted by date. Nice and easy.
With section headings, I'm currently doing this:
One Cursor to select all distinct dates in the dataset
For each distinct date, a separate Cursor to return the items matching that date
Pour the dates (section headings) and separate SimpleCursorAdapters for each date's items, into my custom adapter.
This requires many more database queries and Cursors to be generated than I want, and there's a delay of several seconds before the ListView appears.
I suspect there might be a simpler solution where getView does something clever and detects when the date has changed between successive items, and then sneaks in a new heading by itself, thus requiring just the one Cursor. Can anyone suggest a way of doing this?

I guess the easiest way would be to check within every getView call whether the previous item has a different date, and if so to simply embed the header within the current view.

You can try http://code.google.com/p/android-section-list/, which requires just single cursor behind (returning cursor + section in one object). However it will anyhow have to go through all the elements (once) to calculate the size of resulting list+headers (needed by list adapter) - so it might still be slow.

Related

How would one go about Re-sorting ListView Items By Date

How would one go about resorting these listview items by date so it displays from newest to oldest. I would figure using a loop in the GetView but i'm unsure about the logic to get it done.
Each one of those list items have a cell containing all the information about the listitem, such as a date, title and icon.
Would appreciate any help on the issue.
I resolved this at the database level by using ORDER BY as several people had mentioned in the comments. Only reason before I couldnt do this is because they were all separate queries, but I combined them all together using UNION.

Android Adapt Data from a SQLite Database to a Listview

EDIT: After spending almost all day on this OutOfMemory Error I was getting, turns out I simply wasnt advancing a cursor. However, I still wish to obtain an answer for my question below. To clarify, my question is:
Is it faster to make a custom adapter for a listview that hooks directly into the database to retrieve the data, or should an arraylist of that data be made first and then passed into a default arrayadapter?
I am currently working on an application and as a part of one of its functions I need to be able to take data from an internal database and display parts of it in various listviews. These listviews are all linked together in a ViewFlipper to make it easy to move between the views. I am working with about 5000 values maximum at once. (That is the stress size for the data set that I am tasked to work with).
Should I write a custom adapter that directly links to the database and extracts the values, or is there a better way to go about this? I tried to create a sort of wrapper class for the database that would extract all necessary data from the database and place it into a POJO but i keep getting OutOfMemory exceptions (5 string values * 5000 rows = 25000 strings doesnt seem to be nicely accepted in my case).
Not with the same amount of values, 5000 but I had a similar problem.
I ended up using a private arrayList on a ListAdapter, the list will contain only partial lists, for example 100 items.
Your cursor can initially contain the values to fill the firsts 100 items and when you scroll down looking for more items you can launch another cursor to retreive the next 50 items. Controlling a range of 100-150 items at your arrayList by adding/removing new/old items and refreshing the adapter.
I vote up your question because maybe someone find a better way to do it and I would like to know as well.

Multiple ListAdapters or a single one, using filtering (Android Performance)

Try to focus on general "dos and donts" regarding lists, e.g. is
adding and removing 30 items of a 200 item list better then clearing
and repopulating? Or any other tips in this area - I cant really try
on my phone, to fast for that :-)
Is there any way to calculate the memory overhead / calculation power of list operations. The background is as following:
I have a list view on a page, the page has e.g. 3 Tabs at the bottom (All, Search, Recent). Now if you click on a tab, the listview should show you the approriate items.
There are two different approaches now, one is:
Use a single ListAdapter, filter the items accordingly
- If you click All, just put all items from the DB into it
- If you click Recent, just put the items which meet the requirements
Use two (three..) ListAdapters, one for each category
- If you click All, setAdapter() of list to the approriate one
- If you click Recent, setAdapter() to appropriate one
We are talking about a list of 200 items, which are complex objects created out of a database. When e.g. searching for an item, you enter part of the title, and the list should only show the appropriate items. The items will not be recreated, I would query for the IDs only, and use the buffered items (see later on datastructure).
What I am also not sure about is "where to filter", I could do it in the database (select from where title LIKE abc) and then EITHER:
remove not matching items from the list and add all matching (but not included) items
clear the whole list, add all matching items
Again, to clarify the structure of the App data:
Database with raw simple entries (with IDs + title + ...)
HashSet with complex entries, created once from DB, readonly + always all entries
ArrayList of current entries shown in a listView
I hope you get my drift, I am trying to get a feel for "expensive" operations. Perhaps, as a last motivation to answer, I will write some cases down, and you can give an opinion about how costly they are:
Selecting N items (ID only) from DB with "title LIKE"
Iterating a list of 200 items with a "title.contains()" and using only matches
Removing 100 items from an arraylist SHOWN by an list view
Removing 100 items from an arraylist not shown, then connect and show
Thanks for any feedback, or any tips for bad practices. Especially possible event trigger problems by working on visible list elements, instead of doing it first "in the background" and then setting a new ListAdapter
I see you have accepted an answer already, but I think I don't agree, because ArrayList has to copy all elements, if in the middle is an element added or removed.
I understand you already have a HashSet with all entries.
In that case, I believe the most efficient adapter is a custom ListAdapter inspired from ArrayAdapter
your adapter stores an ArrayList mAllObjects of all entries (for the "all" tab).
your adapter stores an ArrayList mRecentObject of recent entries (for the "recent" tab)
your adapter stores an ArrayList mMatchObject of matching entries (for the "search" tab)
your adapter has two filters
the recent filter returns the mRecentObject list (and creates it if it does not exist already)
the match filter creates a new mMatchObject list and adds matching elements. There is no optimization to be done here. the delete()method on an ArrayList is O(n).
I'm not sure I understand what you're trying to do with the whole list thing, but regarding filtering, you should do it on the database side (in the select statement you mentioned)... especially since this application is for mobile (given the comment at the top) and you would want to offload intensive operations to server side rather than leave them on mobile.
Slight stab in the dark. From the (fairly cursory) "Designing for Performance" document, it would seem that object creation, especially short-lived ones, have very high cost. I would interpret this as coming from two places: 1) object creation overhead (especially for complex objects), and 2) invoking the GC when these go out of scope or are explicitly destroyed.
Thus, as a starting point, I'd argue that you would want to do the work in the DB, and push the deltas to the view. So, per your original question, do:
remove not matching items from the list and add all matching (but not included) items
I suppose you could write a synthetic benchmark for this to get a feel for the differences in speed. However, in my own code, I try and avoid short-lived objects as much as possible as suggested by the performance document. The impact of the GC is heavyweight, as it often will disturb the UI thread and make it hiccup as it goes about its work.

What's the best way to handle a list view whose cursor gets frequent reads and writes?

I am building an Inventory application. The items are shown in a grid view and each cell of the grid view also has a TextView in the upper right corner that displays the available quantity of the item. The user can single click on the gridview cell to increase the quantity or long click to decrease it.
I am currently using a class derived from SimpleCursorAdapter to display the data, but I am not sure about how to update the quantity in the DB. I am afraid that if I write directly to the DB and then create a new cursor and change cursor that the application might become bogged down if the user clicks repeatedly (say to add 10 items)
I have considered copying the data from the query cursor to an array in the Activity and then using an ArrayAdapter but this seems kludgy.
I have also thought about creating an array in my SimpleCursorAdapter which would cache items that have been modified and then save those items when pausing...
Is there a better way? A more Android way?
I guess this comes down to: what is the best way to make rapid changes in the DB and UI?
I don't know much about Cursors in this regard, but I would create a custom ArrayAdapter based on a model object rather than a Cursor. That's just a personal preference, but by doing this I don't have to make any assumptions about the Cursor implementation or know it inside and out.
Let's say you're displaying a collection of type Item in your grid. I would create a class called ItemsList that derives from ArrayList<Item> and my adapter would derive from ArrayAdapter<Item>. The reason you create a wrapper around the ArrayList is that you can allow the user to interact with it freely and mark it as "dirty" and allow it to update the database asynchronously. This way, you just call notifyDataSetChanged() on your adapter and you don't have to think about the overhead of updating the db...you've separated interacting with the collection being displayed and the process of updating the persistent storage.
Btw...this video is a must when working with ListViews and Adapters if you haven't already seen it:
http://www.youtube.com/watch?v=wDBM6wVEO70
You could use a regular listView and a regular Adapter with a list (arraylist) of items in it. Every time user clicks or long clicks you can edit the list in your adapter and notifyDataChanged() which will reflect the list changes on your listView. If you want to keep your list after user quits your application you can use either database(for bigger amount of data) or preferences (for smaller data amount).

draw a list with sections in android

i have to draw a listview with sections.
To be precise i have to display events in the different months of the year. In this the month name becomes the header of the section and the event in that month become the data inside the section.
i am currently getting data in a hashmap, with the month name as the key and an array on events in that month as an object.
how do i achieve this effect? In iphone app development i believe there is a inbuilt functionality for this, is there such a provision in android?
thank you in advance.
NOTE:
why can't i use a TableView inside a ScrollView to do the above? There is no need to go through adapters and all when i can do this. The process should become very less complex.
Due to the lack of built-in support for sectional header lists, we have to deal with section-header and caption views separably, where sectional-header should be non-clickable and should not be counted as a ListView child. For this you have to override some methods like getView, getCount etc of an efficient adapter.
Search separatedListAdapter for more references.

Categories

Resources