java.util.ArrayList.throwIndexOutOfBoundsException

2019-08-11 07:42发布

问题:

Can someone help me understand what is wrong with this code?
I want to be able to add all contacts associated with the query to a ArrayList. But using just the 'add' command make the loop apparently override it and make the size 1 again. But using the 'add' method with a index causes this error. 'IndexOutOfBoundsError'. pls. do help me.

This the error log.

08-14 21:36:29.893  20439-20439/? E/Zygote﹕ MountEmulatedStorage()
08-14 21:36:29.893  20439-20439/? E/Zygote﹕ v2
08-14 21:36:29.943  20439-20439/? E/SELinux﹕ [DEBUG] get_category: variable     
seinfo: default sensitivity: NULL, cateogry: NULL
08-14 21:36:44.973  20439-20439/com.cmpe277.personalassistant E/MA﹕ 
search_intent_has_started
08-14 21:36:45.103  20439-20439/com.cmpe277.personalassistant E/DU﹕ 
startQuery has launched
08-14 21:36:45.103  20439-20439/com.cmpe277.personalassistant E/DU﹕ query =  
chemist
08-14 21:36:45.383  20439-20439/com.cmpe277.personalassistant 
E/CLoaderCallbacks﹕ Nothing is null?!
08-14 21:36:53.293  20439-20439/com.cmpe277.personalassistant E/MA﹕ 
search_intent_has_started
08-14 21:36:53.393  20439-20439/com.cmpe277.personalassistant E/DU﹕ 
startQuery has launched
08-14 21:36:53.393  20439-20439/com.cmpe277.personalassistant E/DU﹕ query =  
leela ashok
08-14 21:36:53.533  20439-20439/com.cmpe277.personalassistant 
E/CLoaderCallbacks﹕ Nothing is null?!
08-14 21:36:53.563  20439-20439/com.cmpe277.personalassistant 
E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.cmpe277.personalassistant, PID: 20439
java.lang.IndexOutOfBoundsException: Invalid index 1, size is 0
        at 
java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
        at java.util.ArrayList.add(ArrayList.java:147)
        at  

com.cmpe277.personalassistant.ContactablesLoaderCallbacks.onLoadFinished(ContactablesLoaderCallbacks.java:117)
        at com.cmpe277.personalassistant.ContactablesLoaderCallbacks.onLoadFinished(ContactablesLoaderCallbacks.java:22)
        at android.app.LoaderManagerImpl$LoaderInfo.callOnLoadFinished(LoaderManager.java:483)
        at android.app.LoaderManagerImpl$LoaderInfo.onLoadComplete(LoaderManager.java:451)
        at android.content.Loader.deliverResult(Loader.java:144)
        at android.content.CursorLoader.deliverResult(CursorLoader.java:109)
        at android.content.CursorLoader.deliverResult(CursorLoader.java:42)
        at android.content.AsyncTaskLoader.dispatchOnLoadComplete(AsyncTaskLoader.java:265)
        at android.content.AsyncTaskLoader$LoadTask.onPostExecute(AsyncTaskLoader.java:92)
        at android.os.AsyncTask.finish(AsyncTask.java:632)
        at android.os.AsyncTask.access$600(AsyncTask.java:177)
        at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:145)
        at android.app.ActivityThread.main(ActivityThread.java:5832)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)

This is my code:

package com.kishore_kumar.callbacks;

import android.app.Activity;
import android.app.LoaderManager;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds;
import android.util.Log;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * Helper class to handle all the callbacks that occur when interacting with    
loaders.  Most of the
 * interesting code in this sample app will be in this file.
 */
public class ContactablesLoaderCallbacks implements   
LoaderManager.LoaderCallbacks<Cursor> {

Context mContext;

int counter = 0;

public static final String QUERY_KEY = "query";

public static final String TAG = "CLoaderCallbacks";

public ContactablesLoaderCallbacks(Context context) {
    mContext = context;
}

@Override
public Loader<Cursor> onCreateLoader(int loaderIndex, Bundle args) {
    // Where the Contactables table excels is matching text queries,
    // not just data dumps from Contacts db.  One search term is used to query
    // display name, email address and phone number.  In this case, the 
query was extracted
    // from an incoming intent in the handleIntent() method, via the
    // intent.getStringExtra() method.

    // BEGIN_INCLUDE(uri_with_query)
    String query = args.getString(QUERY_KEY);
    Uri uri = Uri.withAppendedPath(
            CommonDataKinds.Contactables.CONTENT_FILTER_URI, query);
    // END_INCLUDE(uri_with_query)


    // BEGIN_INCLUDE(cursor_loader)
    // Easy way to limit the query to contacts with phone numbers.
    String selection =
            CommonDataKinds.Contactables.HAS_PHONE_NUMBER + " = " + 1;

    // Sort results such that rows for the same contact stay together.
    String sortBy = CommonDataKinds.Contactables.LOOKUP_KEY;

    return new CursorLoader(
            mContext,  // Context
            uri,       // URI representing the table/resource to be queried
            null,      // projection - the list of columns to return.  Null 
means "all"
            selection, // selection - Which rows to return (condition rows 
must match)
            null,      // selection args - can be provided separately and 
subbed into selection.
            sortBy);   // string specifying sort order
    // END_INCLUDE(cursor_loader)
}

@Override
public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
    TextView tv  = (TextView) 
((Activity)mContext).findViewById(R.id.sample_output);
    if(tv == null) {
        Log.e(TAG, "TextView is null?!");
    } else if (mContext == null) {
        Log.e(TAG, "Context is null?");
    } else {
        Log.e(TAG, "Nothing is null?!");
    }

    // Reset text in case of a previous query
    tv.setText(mContext.getText(R.string.intro_message) + "\n\n");

    if (cursor.getCount() == 0) {
        return;
    }

    // Pulling the relevant value from the cursor requires knowing the 
column index to pull
    // it from.
    // BEGIN_INCLUDE(get_columns)
    int phoneColumnIndex = 
cursor.getColumnIndex(CommonDataKinds.Phone.NUMBER);
    int emailColumnIndex = 
cursor.getColumnIndex(CommonDataKinds.Email.ADDRESS);
    int nameColumnIndex =  
cursor.getColumnIndex(CommonDataKinds.Contactables.DISPLAY_NAME);
    int lookupColumnIndex = 
cursor.getColumnIndex(CommonDataKinds.Contactables.LOOKUP_KEY);
    int typeColumnIndex = 
cursor.getColumnIndex(CommonDataKinds.Contactables.MIMETYPE);
    // END_INCLUDE(get_columns)

    cursor.moveToFirst();
    // Lookup key is the easiest way to verify a row of data is for the same
    // contact as the previous row.
    String lookupKey = "";
    do {
        // BEGIN_INCLUDE(lookup_key)
        String currentLookupKey = cursor.getString(lookupColumnIndex);
        if (!lookupKey.equals(currentLookupKey)) {
            String displayName = cursor.getString(nameColumnIndex);
            tv.append(displayName + "\n");
            lookupKey = currentLookupKey;
        }
        // END_INCLUDE(lookup_key)

        // BEGIN_INCLUDE(retrieve_data)
        // The data type can be determined using the mime type column.
        String mimeType = cursor.getString(typeColumnIndex);
        if (mimeType.equals(CommonDataKinds.Phone.CONTENT_ITEM_TYPE)) {
            tv.append("\tPhone Number: " + 
 cursor.getString(phoneColumnIndex) + "\n");
 //@TeneCursum this is roughly about where the error gets thrown out          
 ArrayList<String> mylist = new ArrayList<String>();
            mylist.add(counter, cursor.getString(phoneColumnIndex)); //this 
adds an element to the list.
            tv.append("size = "+mylist.size());
            counter++;
        } else if (mimeType.equals(CommonDataKinds.Email.CONTENT_ITEM_TYPE)) 
{
            tv.append("");
        }
        // END_INCLUDE(retrieve_data)

        // Look at DDMS to see all the columns returned by a query to 
Contactables.
        // Behold, the firehose!
        for(String column : cursor.getColumnNames()) {
            Log.d(TAG, column + column + ": " +
                    cursor.getString(cursor.getColumnIndex(column)) + "\n");
        }
    } while (cursor.moveToNext());
}

@Override
public void onLoaderReset(Loader<Cursor> cursorLoader) {
}
}

I am a beginner. So please do help me understand.

回答1:

Put ArrayList<String> mylist = new ArrayList<String>(); before the do { construct. The problem is that you are incrementing counter, but you're making a new List each time. The second time that the do-while is executing, the counter = 1 and the array is new, so it's size it 0. Hence, adding with myList.add(1, object) will fail.



回答2:

ArrayList<String> mylist = new ArrayList<String>(); 

is put too late in the code. It should be created before any operations can happen on it.

What you are actually doing is refreshing and re-creating mylist everytime. Therefore, when you run it a second time through the loop, mylist was remade, and it has nothing inside of it.

You are accessing the 1st index of a freshly made ArrayList that only contains 1 object, even though you are searching for 2 objects since count is 1. (Remember? Arrays start at 0.)



回答3:

You are creating an empty Array (with lenght = 0) and you try to put into it an element in a different position of 0. Watch you are creating an empty array every time. If you know how many contacts have you got, you can create an Array with the constructor new ArrayList(int initialCapacity)