From 34783aac261f55ba1fbc2ccb60fd0bdb12fdf52a Mon Sep 17 00:00:00 2001 From: Gilles Debunne Date: Wed, 24 Mar 2010 14:47:28 -0700 Subject: [PATCH] Fixes for HeaderViewListAdapter. Null header and footer, as used by CTS tests, were no longer supported. Added a static empty list to avoid repetitive null tests in that case. Fixed getItem/getItemId/getView to handle corner cases. Changed ListAdapter isEnabled documentation for invalid positions. http://b/issue?id=2527753 Change-Id: I55e5bf21cb0673d906caa7c669987a6ae869d90f --- .../android/widget/HeaderViewListAdapter.java | 80 +++++++++++-------- core/java/android/widget/ListAdapter.java | 3 + 2 files changed, 50 insertions(+), 33 deletions(-) diff --git a/core/java/android/widget/HeaderViewListAdapter.java b/core/java/android/widget/HeaderViewListAdapter.java index 981996a30b5f7..ca97987dd9805 100644 --- a/core/java/android/widget/HeaderViewListAdapter.java +++ b/core/java/android/widget/HeaderViewListAdapter.java @@ -28,7 +28,6 @@ import java.util.ArrayList; * associated data objects. *

This is intended as a base class; you will probably not need to * use this class directly in your own code. - * */ public class HeaderViewListAdapter implements WrapperListAdapter, Filterable { @@ -130,43 +129,53 @@ public class HeaderViewListAdapter implements WrapperListAdapter, Filterable { } public boolean isEnabled(int position) { + // Header (negative positions will throw an ArrayIndexOutOfBoundsException) int numHeaders = getHeadersCount(); - if (mAdapter != null && position >= numHeaders) { - int adjPosition = position - numHeaders; - int adapterCount = mAdapter.getCount(); - if (adjPosition >= adapterCount) { - return mFooterViewInfos.get(adjPosition - adapterCount).isSelectable; - } else { - return mAdapter.isEnabled(adjPosition); - } - } else if (position < numHeaders) { + if (position < numHeaders) { return mHeaderViewInfos.get(position).isSelectable; } - return true; + + // Adapter + final int adjPosition = position - numHeaders; + int adapterCount = 0; + if (mAdapter != null) { + adapterCount = mAdapter.getCount(); + if (adjPosition < adapterCount) { + return mAdapter.isEnabled(adjPosition); + } + } + + // Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException) + return mFooterViewInfos.get(adjPosition - adapterCount).isSelectable; } public Object getItem(int position) { + // Header (negative positions will throw an ArrayIndexOutOfBoundsException) int numHeaders = getHeadersCount(); - if (mAdapter != null && position >= numHeaders) { - int adjPosition = position - numHeaders; - int adapterCount = mAdapter.getCount(); - if (adjPosition >= adapterCount) { - return mFooterViewInfos.get(adjPosition - adapterCount).data; - } else { - return mAdapter.getItem(adjPosition); - } - } else if (position < numHeaders) { + if (position < numHeaders) { return mHeaderViewInfos.get(position).data; } - return null; + + // Adapter + final int adjPosition = position - numHeaders; + int adapterCount = 0; + if (mAdapter != null) { + adapterCount = mAdapter.getCount(); + if (adjPosition < adapterCount) { + return mAdapter.getItem(adjPosition); + } + } + + // Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException) + return mFooterViewInfos.get(adjPosition - adapterCount).data; } public long getItemId(int position) { int numHeaders = getHeadersCount(); if (mAdapter != null && position >= numHeaders) { int adjPosition = position - numHeaders; - int adapterCnt = mAdapter.getCount(); - if (adjPosition < adapterCnt) { + int adapterCount = mAdapter.getCount(); + if (adjPosition < adapterCount) { return mAdapter.getItemId(adjPosition); } } @@ -181,19 +190,24 @@ public class HeaderViewListAdapter implements WrapperListAdapter, Filterable { } public View getView(int position, View convertView, ViewGroup parent) { + // Header (negative positions will throw an ArrayIndexOutOfBoundsException) int numHeaders = getHeadersCount(); - if (mAdapter != null && position >= numHeaders) { - int adjPosition = position - numHeaders; - int adapterCount = mAdapter.getCount(); - if (adjPosition >= adapterCount) { - return mFooterViewInfos.get(adjPosition - adapterCount).view; - } else { - return mAdapter.getView(adjPosition, convertView, parent); - } - } else if (position < numHeaders) { + if (position < numHeaders) { return mHeaderViewInfos.get(position).view; } - return null; + + // Adapter + final int adjPosition = position - numHeaders; + int adapterCount = 0; + if (mAdapter != null) { + adapterCount = mAdapter.getCount(); + if (adjPosition < adapterCount) { + return mAdapter.getView(adjPosition, convertView, parent); + } + } + + // Footer (off-limits positions will throw an ArrayIndexOutOfBoundsException) + return mFooterViewInfos.get(adjPosition - adapterCount).view; } public int getItemViewType(int position) { diff --git a/core/java/android/widget/ListAdapter.java b/core/java/android/widget/ListAdapter.java index a0351450bfa24..0fd2e7090b463 100644 --- a/core/java/android/widget/ListAdapter.java +++ b/core/java/android/widget/ListAdapter.java @@ -36,6 +36,9 @@ public interface ListAdapter extends Adapter { /** * Returns true if the item at the specified position is not a separator. * (A separator is a non-selectable, non-clickable item). + * + * The result is unspecified if position is invalid. An {@link ArrayIndexOutOfBoundsException} + * should be thrown in that case for fast failure. * * @param position Index of the item * @return True if the item is not a separator