Search code examples
androidandroid-asynctaskandroid-arrayadaptercommonsware-cwac

ArrayOutOfBounds When using addHeaderView() with EndlessAdapter


I am using EndlessAdapter by Commonsware. When I have a header view added I get my listView, this I get this error and LogCat:

04-22 17:06:15.200: E/AndroidRuntime(6401): FATAL EXCEPTION: main
04-22 17:06:15.200: E/AndroidRuntime(6401): java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
04-22 17:06:15.200: E/AndroidRuntime(6401):     at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at java.util.ArrayList.get(ArrayList.java:304)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.widget.HeaderViewListAdapter.isEnabled(HeaderViewListAdapter.java:164)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.widget.ListView.dispatchDraw(ListView.java:3207)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.draw(View.java:13715)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.widget.AbsListView.draw(AbsListView.java:3653)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12650)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12694)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2910)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12588)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12694)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2910)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12588)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12694)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2910)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12588)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12694)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2910)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12588)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12694)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2910)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12588)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12694)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2910)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12588)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12694)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2910)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12588)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12694)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:2910)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12588)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.View.getDisplayList(View.java:12694)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:1198)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.ViewRootImpl.draw(ViewRootImpl.java:2173)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2045)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1854)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:989)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4351)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.Choreographer.doCallbacks(Choreographer.java:562)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.Choreographer.doFrame(Choreographer.java:532)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.os.Handler.handleCallback(Handler.java:725)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.os.Handler.dispatchMessage(Handler.java:92)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.os.Looper.loop(Looper.java:137)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at android.app.ActivityThread.main(ActivityThread.java:5226)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at java.lang.reflect.Method.invokeNative(Native Method)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at java.lang.reflect.Method.invoke(Method.java:511)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
04-22 17:06:15.200: E/AndroidRuntime(6401):     at dalvik.system.NativeStart.main(Native Method)

If I remove the headerview, I get past this point.

Supplemental: Here is other code in case this is unrelated to header view:

public class EndlessProfileAdapter extends EndlessAdapter implements
            IItemsReadyListener {

        private boolean hasMoreData = true;
        private RotateAnimation rotate = null;
        private View pendingView = null;
        private ArrayList<ProfileReview> profileList;

        public EndlessProfileAdapter(Context context,
                ArrayList<ProfileReview> profileList, Typeface tf) {
            super(new ProfileAdapter(context, profileList, tf));

            this.profileList = profileList;

            rotate = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF,
                    0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
            rotate.setDuration(600);
            rotate.setRepeatMode(Animation.RESTART);
            rotate.setRepeatCount(Animation.INFINITE);

        }

@Override
protected boolean cacheInBackground() throws Exception {
    Log.d("Cache Array Size", String.valueOf(profileList.size()));
    new ReviewTask(this, profileList.size()).execute();
    return hasMoreData;
}

@Override
protected void appendCachedData() {

}

void startProgressAnimation() {
    if (pendingView != null) {
        pendingView.startAnimation(rotate);
    }
}

public void onItemsReady(ArrayList<ProfileReview> data) {

    profileList.addAll(data);
    endlessAdapter.onDataReady();
    hasMoreData = profileList.isEmpty();
}

Inside Task onPostExecute():

profileList = new ArrayList<ProfileReview>();

            for (int i = startPoint; i < startPoint + 10; i++) {
                ProfileReview p = new ProfileReview(itemIdList.get(i),
                        reviewIdList.get(i), reviews.get(i), datelist.get(i),
                        itemslist.get(i), ratings.get(i), cats.get(i));
                profileList.add(p);
            }

            return profileList;

The EndlessAdapter takes groups of ten in the list. The first 10 work... but on 11, it crashes. The LogCat crash actually happens on the second round of 10 (so the 11th item after the user scrolls past the first 10 in the list), and crashes just before profileList.add(p);

Updated with Requested Information

inside onActivityCreated():

       // for adapter constructor 
       tf = Typeface.createFromAsset(getActivity().getAssets(),
            "fonts/listitemfont.ttf");


   LayoutInflater inflater = getActivity().getLayoutInflater();

    ViewGroup header = (ViewGroup) inflater.inflate(
            R.layout.profile_header, listView, false);

    listView = getListView();
    listView.addHeaderView(header, null, false);

            // stuff like settings up buttons inside header

            // just before end of  `onActivityCreated()`

        if (endlessAdapter == null) {
           if (getActivity() != null) {

            profileList = new ArrayList<ProfileReview>();
            endlessAdapter = new EndlessProfileAdapter(getActivity(),
                    profileList, tf);
            endlessAdapter.setRunInBackground(false);
            listView.setAdapter(endlessAdapter);
        }
    }

Solution

  • EndlessAdapter is not going to be able to support header or footer views. The HeaderListViewAdapter that is created when you use header or footer views makes some assumptions about the underlying adapter that are not always going to be the case with an EndlessAdapter.

    I have updated the EndlessAdapter documentation to point out the limitation.