From d2559dcaf0994cb01b7db9400a210ca3f341855c Mon Sep 17 00:00:00 2001 From: Adrian Ulrich Date: Sat, 26 Nov 2016 20:51:43 +0100 Subject: [PATCH] Fix crash in listview setData() might get called late after a queue update. If the listview already started to draw, it might trigger a panic if a count mismatch was detected --- .../android/vanilla/ShowQueueAdapter.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/ch/blinkenlights/android/vanilla/ShowQueueAdapter.java b/src/ch/blinkenlights/android/vanilla/ShowQueueAdapter.java index eb98757e..b696f244 100644 --- a/src/ch/blinkenlights/android/vanilla/ShowQueueAdapter.java +++ b/src/ch/blinkenlights/android/vanilla/ShowQueueAdapter.java @@ -40,6 +40,10 @@ public class ShowQueueAdapter extends BaseAdapter { * The position we are going to mark as 'active' */ private int mHighlightRow; + /** + * The cached number of songs + */ + private int mSongCount; /** * The context to use */ @@ -65,6 +69,7 @@ public class ShowQueueAdapter extends BaseAdapter { public void setData(PlaybackService service, int pos) { mService = service; mHighlightRow = pos; + mSongCount = service.getTimelineLength(); notifyDataSetChanged(); } @@ -75,7 +80,13 @@ public class ShowQueueAdapter extends BaseAdapter { */ @Override public int getCount() { - return (mService == null ? 0 : mService.getTimelineLength()); + // Note: This is only updated by setData() to avoid races with the listView if + // the timeline changes: The listView checks if getCount() changed without + // a call to notifyDataSetChanged() and panics if it detected such a condition. + // This can happen to us as onLayout() might get called before setData() was called during + // a queue update. So we simply cache the count to avoid this crash and won't update it until + // setData() is called by our parent. + return mSongCount; } /** @@ -86,7 +97,8 @@ public class ShowQueueAdapter extends BaseAdapter { */ @Override public Song getItem(int pos) { - return mService.getSongByQueuePosition(pos); + Song item = mService.getSongByQueuePosition(pos); + return (item != null ? item : new Song(-1)); } /** @@ -125,7 +137,7 @@ public class ShowQueueAdapter extends BaseAdapter { Song song = getItem(position); - if (song != null) { // unlikely to fail but seems to happen in the wild. + if (song.isFilled()) { SpannableStringBuilder sb = new SpannableStringBuilder(song.title); sb.append('\n'); sb.append(song.album+", "+song.artist);