Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to fix notifyDataSetChanged/ListView problems in dynamic Adapter wrapper Android
    primarykey
    data
    text
    <p><strong>Summary:</strong> Trying to dynamically add heading rows to a ListView via a custom adapter wrapper. ListView is having trouble keeping the scroll position in sync. Runnable demo project provided.</p> <p>I would like to dynamically add items to a list based on the values in a CursorAdapter, several positions ahead of what the user is currently viewing. To do this, I have an adapter that wraps the CursorAdapter and keeps the new content indexed in a SparseArray. The ListView needs to be updated when items are added to the custom adapter, but I have met a lot of pitfalls trying to get that to work and would love some advice.</p> <p>The demo project can be downloaded here: <a href="http://dl.dropbox.com/u/15334423/DynamicSectionedList.zip" rel="nofollow">DynamicSectionedList.zip</a></p> <p>In the demo, the headings are added dynamically by looking ahead 10 places to find the correct position where the list items switch to the next letter. Each implementation of notifyDataSetChanged has problems as described:</p> <p><strong>Demo 1</strong> This demo shows the importance of notifyDataSetChanged(). On clicking anything, the app will crash. This is due to some sanity checking in ListView... <code>mItemCount != adapter.getItemCount()</code>. Moral is, we need to notify the list that data has changed.</p> <p><strong>Demo 2</strong> The natural next step is to notify the ListView of changes when changes occur. Unfortunately, doing so while the ListView is scrolling firmly breaks all touch interaction until the app switches out of touch mode. You will need to "fling scroll" far enough to generate new headings in order to notice this. Tapping the screen will not cause the scroll to stop, and once stopped none of the list items will be clickable. This is due to some <code>if (!mDataChanged) { /* do very important stuff */ }</code> code in AbsListView.onTouchEvent().</p> <p><strong>Demo 3</strong> To fix this, Demo 3 introduces a pendingChanges flag and the custom Adapter gains a notifyDataSetChangedIfNeeded() which can be called by the ListView once it has entered a "safe" state for changes. The first point where changes must be notified is in ListView.layoutChildren(), so I overrode that method to first notify of changes if needed, then call through. Fling past at least one heading then click a list item.</p> <p>This doesn't quite work right, though I'm not totally sure why. Tapping or selecting an item with the keyboard/trackball causes the list to refresh without properly syncing the old position. It scrolls to the top of the list which is not acceptable.</p> <p><strong>Demo 4</strong> The scroll problem in Demo 3 can be conquered, at least in touch mode. By adding a call to notifyDataSetChangedIfNeeded() on touch down, the data change happens to take place at such a time that all touch interaction works as expected and the list position is properly synced.</p> <p>However, I can't find an analog for that when the device is not in touch mode, not to mention the fact that it definitely seems like a hack. The list almost always scrolls back to the top, I can't find out what causes it to occasionally maintain the correct position. </p> <p>Since Android is fighting me at each step of the way, I feel like there should be a better approach. Please try the demo, if any fixes can be applied to get it working that would be great!</p> <p>Many thanks to anyone who can look into this, hopefully if we can get the code working it will be useful for others trying to accomplish the same optimization for lists with headings. </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. COThe for loops immediately below `LinearLayout buttons` do not appear to have valid Java syntax. You also appear to be missing any code that populates the list. I recommend you create a full project containing this stuff, ZIP it up, and link to it from your question. Even then, I wouldn't put tremendous odds on your getting much help, as this is a substantial hunk of difficult-to-decipher code, and you're not really asking any questions in your question.
      singulars
    2. COYou might consider starting a 2nd question, expanding upon the real problem ("the amount of data in the list may be quite large and the calculation of the headings may be considered expensive enough to require optimization"). What you have here is something somewhat related to your actual code that attempts to address the real problem. However, it may be simpler for you to get help with the real problem itself, figuring out why "calculation of the headings" is "expensive" and how to address it. Of course, you're also asking this on the Thursday before a holiday weekend...
      singulars
    3. COBTW, FWIW, I wrote up a blog post with my thoughts on adding headings to a `CursorAdapter`: http://commonsware.com/blog/2010/12/30/adding-headings-cursoradapter.html
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload