1

I'm getting an invalid index 0, size is 0 error and can't figure out where this is happening. I've been running the debugger and can't place it. All I know is what happens in my code before and what would happen after. Below I've posted the logcat, the code that finishes before the crash, and what would run after.

Here's the logcat:

  java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
        at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
        at java.util.ArrayList.get(ArrayList.java:308)
        at android.widget.HeaderViewListAdapter.isEnabled(HeaderViewListAdapter.java:164)
        at android.widget.ListView.dispatchDraw(ListView.java:3307)
        at android.view.View.draw(View.java:15174)
        at android.widget.AbsListView.draw(AbsListView.java:4318)
        at android.view.View.updateDisplayListIfDirty(View.java:14096)
        at android.view.View.getDisplayList(View.java:14119)
        at android.view.View.draw(View.java:14895)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3407)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3201)
        at android.view.View.draw(View.java:15174)
        at android.view.View.updateDisplayListIfDirty(View.java:14096)
        at android.view.View.getDisplayList(View.java:14119)
        at android.view.View.draw(View.java:14895)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3407)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3201)
        at android.view.View.updateDisplayListIfDirty(View.java:14091)
        at android.view.View.getDisplayList(View.java:14119)
        at android.view.View.draw(View.java:14895)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3407)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3201)
        at android.view.View.updateDisplayListIfDirty(View.java:14091)
        at android.view.View.getDisplayList(View.java:14119)
        at android.view.View.draw(View.java:14895)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3407)
        at android.support.v4.widget.DrawerLayout.drawChild(DrawerLayout.java:1089)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3201)
        at android.view.View.updateDisplayListIfDirty(View.java:14091)
        at android.view.View.getDisplayList(View.java:14119)
        at android.view.View.draw(View.java:14895)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3407)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3201)
        at android.view.View.updateDisplayListIfDirty(View.java:14091)
        at android.view.View.getDisplayList(View.java:14119)
        at android.view.View.draw(View.java:14895)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3407)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3201)
        at android.view.View.updateDisplayListIfDirty(View.java:14091)
        at android.view.View.getDisplayList(View.java:14119)
        at android.view.View.draw(View.java:14895)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3407)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3201)
        at android.view.View.updateDisplayListIfDirty(View.java:14091)
        at android.view.View.getDisplayList(View.java:14119)
        at android.view.View.draw(View.java:14895)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3407)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3201)
        at android.view.View.updateDisplayListIfDirty(View.java:14091)
        at android.view.View.getDisplayList(View.java:14119)
        at android.view.View.draw(View.java:14895)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3407)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3201)
        at android.view.View.updateDisplayListIfDirty(View.java:14091)
        at android.view.View.getDisplayList(View.java:14119)
        at android.view.View.draw(View.java:14895)
        at android.view.ViewGroup.drawChild(ViewGroup.java:3407)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3201)
        at android.view.View.draw(View.java:15174)
        at android.widget.FrameLayout.draw(FrameLayout.java:592)
        at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2695)
        at android.view.View.updateDisplayListIfDirty(View.java:14096)
        at android.view.View.getDisplayList(View.java:14119)
        at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:266)
        at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:272)
        at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:311)
        at android.view.ViewRootImpl.draw(ViewRootImpl.java:2531)
        at android.view.

Here's my code right before, which it finishes:

   @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    Answer a = null;
    if(position -1 >= 0 && myAnswerNotices.size() > position -1){
        a = myAnswerNotices.get(position-1);
        QuestionFragment.clicked_Question = a.getQuestion();
    }

    // Go to question view
    Intent intent;

    if(QuestionFragment.clicked_Question.getType().equals( "poll"))
        intent = new Intent (getActivity(), PollViewActivity.class);
    else
        intent = new Intent (getActivity(), QuestionViewActivity.class);

    if(a != null) {
        if (preferences.contains("notice_" + a.getObjectId())) {
            editor.remove("notice_" + a.getObjectId());
            editor.commit();
        }

        if (myAnswerNotices != null && !myAnswerNotices.isEmpty() && myAnswerNotices.contains(a))
            myAnswerNotices.remove(a);
    }

    startActivity(intent);

}

Here's the code that should start after:

  @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
    setContentView(R.layout.activity_question_view);

    Toolbar toolbar = (Toolbar) findViewById(R.id.question_view_toolbar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setHomeButtonEnabled(true);

    share = (ImageButton) findViewById(R.id.questionView_share_image_button);
    emailButton = (Button) findViewById(R.id.questionView_email_button);
    title = (TextView) findViewById(R.id.questionView_title_text_view);
    username = (TextView) findViewById(R.id.questionView_askedBy_text_view);
    createdAt = (TextView) findViewById(R.id.questionView_createdAt_text_view);
    followingTextView = (TextView) findViewById(R.id.questionView_follow_textview);

    setupQuestion();
    setListeners();
    setupList();

}

@Colin:

myAnswerNotices is initialized as a member variable:

public class NotificationFragment extends Fragment
    implements AdapterView.OnItemClickListener, SwipeRefreshLayout.OnRefreshListener {

private final List<Answer> myAnswerNotices = new ArrayList<>();

and populated in an AsyncTask: public class RefreshTask extends AsyncTask> {

    @Override
    protected void onPreExecute() {
        mRefreshWrapper.setRefreshing(true);
       // Activity.pinAll();
    }

    @Override
    protected List<Answer> doInBackground(Object... params) {

        //myAnswerNotices.clear();
       // List<Activity> a_list = new ArrayList<>();
        try {
            activityNotifications.addAll(Activity.getQuery()
                    .whereEqualTo(Constants.kQollegeActivityTypeKey, Constants.kQollegeActivityTypeAnswerPosted)
                    .whereEqualTo(Constants.kQollegeActivityToUserKey, ParseUser.getCurrentUser())
                    .whereGreaterThan(Constants.kQollegeQuestionCreatedAtKey, checked)
                    .orderByDescending(Constants.kQollegeQuestionCreatedAtKey)
                    .include(Constants.kQollegeActivityAnswerKey)
                    .find());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        checked = Calendar.getInstance().getTime();
        editor.putLong("notification_checked",checked.getTime());
        editor.commit();


        for(String s : preferences.getAll().keySet()){
            if(s.contains("notice_")){
                String a_id = preferences.getString(s, null);
                if(a_id != null){
                    try {
                        myAnswerNotices.add(Answer.getQuery().get(a_id));
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        for(Activity a : activityNotifications){
            myAnswerNotices.add(a.getAnswer());
        }

        return myAnswerNotices;

    }

    @Override
    protected void onPostExecute(List<Answer> list) {
        if(!myAnswerNotices.isEmpty())
            mHeaderTextView.setVisibility(View.GONE);
        else {
            mHeaderTextView.setText("No notifications");
            mHeaderTextView.setVisibility(View.VISIBLE);
        }

        mRefreshWrapper.setRefreshing(false);

    }

@Varsha: Here is the code relating to my adapter initialization:

NotificationListAdapter mListAdapter = new NotificationListAdapter(getActivity(), R.layout.notification_list_item, myAnswerNotices);
    mRefreshWrapper.getListView().setAdapter(mListAdapter);
    mListAdapter.setNotifyOnChange(true);

@Titus: Here's my entire adapter class:

class NotificationListAdapter extends ArrayAdapter {

private final int mResourceId;
private final LayoutInflater inflater;
private final Context context;
private NotificationListItemHolder notificationView;
private Answer answer;

public NotificationListAdapter(Context ctx, int resourceId, List objects){
    super(ctx,resourceId,objects);
    mResourceId = resourceId;
    inflater = LayoutInflater.from(ctx);
    context = ctx;
}

@Override
public View getView (int position, View convertView, ViewGroup parent) {
    answer = (Answer) getItem(position);

    // Get or create cached eventView
    if(convertView == null){
        convertView =  inflater.inflate(mResourceId, null);
        notificationView = new NotificationListItemHolder(convertView);
        convertView.setTag(notificationView);
    }
    else {
        notificationView = (NotificationListItemHolder) convertView.getTag();
    }
    TextView name = notificationView.getPostedByTextView();
    name.setTag(answer);
    // Fill Data
    fillData();

    name.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            Intent intent = new Intent(context, ProfileActivity.class);
            Answer a = (Answer) v.getTag();
            ParseUser u = a.getPostedBy();

            intent.putExtra("User", u.getObjectId());
            context.startActivity(intent);
        }
    });



    return convertView;
}

private void fillData(){
    try {
        Question q = answer.getQuestion().fetch();
        notificationView.getTitleTextView().setText(q.getTitle());
    } catch (ParseException e) {
        e.printStackTrace();
    }
    notificationView.getPostedByTextView().setText(answer.getPostedByText());
    notificationView.getCreatedAtTextView().setText(answer.getCreatedAtText());
}

}

Pseduosance
  • 305
  • 1
  • 5
  • 16

1 Answers1

11

Note: I don't have enough reputation to comment so writing this answer.

It's seems to getCount() method in adapter just override that method:

if(myAnswerNotices == null || myAnswerNotices.size()>0)
return myAnswerNotices.size();
else 
return 0;

I hope this will help. Thanks

Ramesh Kumar
  • 1,229
  • 14
  • 24
  • How can I override the getCount in the NotificationListAdapter with that if myAnswerNotices is not defined inside the adapter? – Pseduosance Sep 20 '15 at 11:42
  • 1
    @Pseduosance the `myAnswerNotices` is not defined in the adapter but it is referenced by the `objects` variable so, use `object` instead of `myAnswerNotices` – Titus Sep 20 '15 at 11:49
  • @Titus, Thanks, realized it after I made that comment – Pseduosance Sep 20 '15 at 11:53
  • Well I overwrote it, but now nothing is showing up in the listView – Pseduosance Sep 20 '15 at 11:56
  • 1
    @Pseduosance that is probably because you add items to the adapter's list after you add it to the `ListView`. Add this line in the `onPostExecute(...)` method `mListAdapter.notifyDataSetChanged()`. The idea is that you have to refresh the adapter after you change its content. – Titus Sep 20 '15 at 12:01
  • @Titus, I was thinking the same thing, but should it be notified since I enabled setNotifyOnChange? – Pseduosance Sep 20 '15 at 12:07
  • @Pseduosance I'm not sure if that works when you change the list from another thread. – Titus Sep 20 '15 at 12:10
  • @Titus, Well for the sake of testing it, I made the list non empty at the start and it worked! – Pseduosance Sep 20 '15 at 12:11
  • @Pseduosance it seems that `setNotifyOnChange(true)` works only when you modify the adapter directly not the underlying list, [more details here](http://stackoverflow.com/questions/3669325/notifydatasetchanged-example/5092426#5092426) – Titus Sep 20 '15 at 12:14
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/90158/discussion-between-pseduosance-and-titus). – Pseduosance Sep 20 '15 at 12:24
  • @Titus I still haven't been able to solve this. I tried setting it to setNotifyOnChange true, but didn't work. HellI even tried making myAnswerNotices in the notificationFragment Global and use that in the getCount. Then I was able to get the list to not be empty, but clicking on one gave me the original error. – Pseduosance Sep 20 '15 at 13:14
  • Looks like this is gonna result in an NPE if `myAnswerNotices` is `null`. The condition should be rewritten to `myAnswerNotices != null && myAnswerNotices.size() > 0`. However, you might as well skip the `myAnswerNotices.size() > 0` since it will return 0 anyway if the list is empty ;) – natronite Jan 10 '18 at 07:30