在listview中显示数据库值时出现CursorIndexOutOfBoundsException错误

时间:2017-06-15 18:13:41

标签: java android android-sqlite simplecursoradapter

我是Android移动开发的新手。我创建了一个名为EmployeeList的数据库,它位于我的Assets文件夹中。我想从那里获取数据并在我的活动中以列表视图格式显示它。应用程序不断崩溃,我不知道为什么。谢谢你的帮助。

  

这是在线和我自己的示例代码的混合。

DatabaseHelper.java

import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * Created by ahadagali on 6/15/2017.
 */

public class DataBaseHelper extends SQLiteOpenHelper {

    //The Android's default system path of your application database.
    private static String DB_PATH = "/data/data/com.example.ahadagali.fivesdyag/databases/";

    private static String DB_NAME = "EmployeeList";

    private SQLiteDatabase myDataBase;

    private final Context myContext;

    /**
     * Constructor
     * Takes and keeps a reference of the passed context in order to access to the application assets and resources.
     * @param context
     */
    public DataBaseHelper(Context context) {

        super(context, DB_NAME, null, 1);
        this.myContext = context;
    }

    /**
     * Creates a empty database on the system and rewrites it with your own database.
     * */
    public void createDataBase() throws IOException{

        boolean dbExist = checkDataBase();

        if(dbExist){
            //do nothing - database already exist
        }else{

            //By calling this method and empty database will be created into the default system path
            //of your application so we are gonna be able to overwrite that database with our database.
            this.getReadableDatabase();

            try {

                copyDataBase();

            } catch (IOException e) {

                throw new Error("Error copying database");

            }
        }

    }

    /**
     * Check if the database already exist to avoid re-copying the file each time you open the application.
     * @return true if it exists, false if it doesn't
     */
    private boolean checkDataBase(){

        SQLiteDatabase checkDB = null;

        try{
            String myPath = DB_PATH + DB_NAME;
            checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

        }catch(SQLiteException e){

            //database does't exist yet.

        }

        if(checkDB != null){

            checkDB.close();

        }

        return checkDB != null ? true : false;
    }

    /**
     * Copies your database from your local assets-folder to the just created empty database in the
     * system folder, from where it can be accessed and handled.
     * This is done by transfering bytestream.
     * */
    private void copyDataBase() throws IOException {

        //Open your local db as the input stream
        InputStream myInput = myContext.getAssets().open(DB_NAME);

        // Path to the just created empty db
        String outFileName = DB_PATH + DB_NAME;

        //Open the empty db as the output stream
        OutputStream myOutput = new FileOutputStream(outFileName);

        //transfer bytes from the inputfile to the outputfile
        byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer))>0){
            myOutput.write(buffer, 0, length);
        }

        //Close the streams
        myOutput.flush();
        myOutput.close();
        myInput.close();

    }

    public void openDataBase() throws SQLException {

        //Open the database
        String myPath = DB_PATH + DB_NAME;
        myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

    }

    @Override
    public synchronized void close() {

        if(myDataBase != null)
            myDataBase.close();

        super.close();

    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    // Add your public helper methods to access and get content from the database.
    // You could return cursors by doing "return myDataBase.query(....)" so it'd be easy
    // to you to create adapters for your views.

    public Cursor fetchAll() {
        Cursor myCursor;
        myCursor = getReadableDatabase().rawQuery("select * from EmployeeList", null);
        //myDataBase = this.getReadableDatabase();
        if (myDataBase != null) {
            myCursor = getReadableDatabase().rawQuery("select * from EmployeeList", null);
        }
        return myCursor;
    }

}

activityThree.java

import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;


import java.io.IOException;

public class activityThree extends AppCompatActivity {
    Context context;

    TextView name;
    TextView phoneNum;
    TextView jobPos;
    TextView availability;

    ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_three);

        name = (TextView)findViewById(R.id.tv_fullName);
        phoneNum = (TextView)findViewById(R.id.tv_phoneNum);
        jobPos = (TextView)findViewById(R.id.tv_jobPosition);
        availability = (TextView) findViewById(R.id.tv_availability);

        DataBaseHelper myDbHelper = new DataBaseHelper(context);
        myDbHelper = new DataBaseHelper(this);

        try {

            myDbHelper.createDataBase();

        } catch (IOException ioe) {

            throw new Error("Unable to create database");

        }

        try {

            myDbHelper.openDataBase();

        }catch(SQLException sqle){

            throw sqle;

        }

        Cursor AllEmployees = myDbHelper.fetchAll();



        AllEmployees.moveToFirst();
        while (!AllEmployees.isAfterLast()){
            AllEmployees.moveToNext();
        }

        String[] from = {AllEmployees.getString(1), AllEmployees.getString(2), AllEmployees.getString(3), AllEmployees.getString(4)};
        int [] to = {R.id.tv_fullName, R.id.tv_phoneNum, R.id.tv_jobPosition, R.id.tv_availability};
        ListAdapter adapter = new SimpleCursorAdapter(this, R.layout.item_listview, AllEmployees, from, to, 0);
        ListView myList = (ListView)findViewById(R.id.listView);
        myList.setAdapter(adapter);


    }
}

activity_three.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

item_listview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF"
    android:paddingBottom="5dp"
    android:paddingLeft="10dp"
    android:paddingRight="10dp"
    android:paddingTop="10dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tv_fullName"
        android:text="Name"
        android:textColor="#4bb6d6"
        android:textSize="20dp"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tv_phoneNum"
        android:text="734"
        android:textColor="#b30000"
        android:textSize="18dp"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tv_jobPosition"
        android:text="Job Position"
        android:textSize="16dp"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tv_availability"
        android:text="Availability"
        android:textSize="16dp"/>

</LinearLayout>

错误记录

06-15 07:09:00.579 27137-27165/com.example.ahadagali.fivesdyag I/OpenGLRenderer: Initialized EGL, version 1.4
06-15 07:09:00.579 27137-27165/com.example.ahadagali.fivesdyag D/OpenGLRenderer: Swap behavior 1
06-15 07:09:00.579 27137-27165/com.example.ahadagali.fivesdyag W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
06-15 07:09:00.579 27137-27165/com.example.ahadagali.fivesdyag D/OpenGLRenderer: Swap behavior 0
06-15 07:09:00.591 1296-1406/? D/gralloc_ranchu: gralloc_alloc: format 1 and usage 0x900 imply creation of host color buffer
06-15 07:09:00.631 1296-1406/? D/gralloc_ranchu: gralloc_alloc: format 1 and usage 0x900 imply creation of host color buffer
06-15 07:09:00.695 27137-27137/com.example.ahadagali.fivesdyag W/art: Before Android 4.1, method int android.support.v7.widget.ListViewCompat.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView
06-15 07:09:00.782 1540-1598/system_process I/ActivityManager: Displayed com.example.ahadagali.fivesdyag/.MainActivity: +678ms
06-15 07:09:00.818 1296-1296/? W/SurfaceFlinger: couldn't log to binary event log: overflow.
06-15 07:09:00.969 1540-1598/system_process D/gralloc_ranchu: gralloc_unregister_buffer: exiting HostConnection (is buffer-handling thread)
06-15 07:09:01.903 1655-1655/com.android.inputmethod.latin I/LatinIME: Starting input. Cursor position = 0,0
06-15 07:09:01.909 1296-3089/? D/gralloc_ranchu: gralloc_alloc: format 1 and usage 0x900 imply creation of host color buffer
06-15 07:09:01.933 1296-3089/? D/gralloc_ranchu: gralloc_alloc: format 1 and usage 0x900 imply creation of host color buffer
06-15 07:09:01.973 1296-3089/? D/gralloc_ranchu: gralloc_alloc: format 1 and usage 0x900 imply creation of host color buffer
06-15 07:09:03.531 1655-1655/com.android.inputmethod.latin I/LatinIME: Starting input. Cursor position = 0,0
06-15 07:09:03.536 27137-27137/com.example.ahadagali.fivesdyag W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
06-15 07:09:04.350 1540-2981/system_process I/ActivityManager: START u0 {cmp=com.example.ahadagali.fivesdyag/.activityTwo (has extras)} from uid 10073 on display 0
06-15 07:09:04.389 1296-1336/? D/gralloc_ranchu: gralloc_alloc: format 1 and usage 0x900 imply creation of host color buffer
06-15 07:09:04.416 1296-1337/? D/gralloc_ranchu: gralloc_alloc: format 1 and usage 0x900 imply creation of host color buffer
06-15 07:09:04.452 1296-1337/? D/gralloc_ranchu: gralloc_alloc: format 1 and usage 0x900 imply creation of host color buffer
06-15 07:09:04.588 1540-1598/system_process I/ActivityManager: Displayed com.example.ahadagali.fivesdyag/.activityTwo: +232ms
06-15 07:09:04.591 27137-27137/com.example.ahadagali.fivesdyag W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
06-15 07:09:04.591 27137-27137/com.example.ahadagali.fivesdyag W/IInputConnectionWrapper: finishComposingText on inactive InputConnection
06-15 07:09:06.247 1540-1554/system_process I/ActivityManager: START u0 {cmp=com.example.ahadagali.fivesdyag/.activityThree} from uid 10073 on display 0
06-15 07:09:06.280 27137-27137/com.example.ahadagali.fivesdyag D/AndroidRuntime: Shutting down VM
06-15 07:09:06.281 27137-27137/com.example.ahadagali.fivesdyag E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                 Process: com.example.ahadagali.fivesdyag, PID: 27137
                                                                                 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ahadagali.fivesdyag/com.example.ahadagali.fivesdyag.activityThree}: android.database.CursorIndexOutOfBoundsException: Index 4 requested, with a size of 4
                                                                                     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
                                                                                     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
                                                                                     at android.app.ActivityThread.-wrap12(ActivityThread.java)
                                                                                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
                                                                                     at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                     at android.os.Looper.loop(Looper.java:154)
                                                                                     at android.app.ActivityThread.main(ActivityThread.java:6119)
                                                                                     at java.lang.reflect.Method.invoke(Native Method)
                                                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                                                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
                                                                                  Caused by: android.database.CursorIndexOutOfBoundsException: Index 4 requested, with a size of 4
                                                                                     at android.database.AbstractCursor.checkPosition(AbstractCursor.java:460)
                                                                                     at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
                                                                                     at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
                                                                                     at com.example.ahadagali.fivesdyag.activityThree.onCreate(activityThree.java:68)
                                                                                     at android.app.Activity.performCreate(Activity.java:6679)
                                                                                     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                                                                                     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2618)
                                                                                     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) 
                                                                                     at android.app.ActivityThread.-wrap12(ActivityThread.java) 
                                                                                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) 
                                                                                     at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                                     at android.os.Looper.loop(Looper.java:154) 
                                                                                     at android.app.ActivityThread.main(ActivityThread.java:6119) 
                                                                                     at java.lang.reflect.Method.invoke(Native Method) 
                                                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
                                                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 
06-15 07:09:06.282 1540-2982/system_process W/ActivityManager:   Force finishing activity com.example.ahadagali.fivesdyag/.activityThree
06-15 07:09:06.286 1540-2982/system_process W/ActivityManager:   Force finishing activity com.example.ahadagali.fivesdyag/.activityTwo
06-15 07:09:06.294 1302-1422/? D/AudioFlinger: mixer(0xa6403a40) throttle end: throttle time(43)
06-15 07:09:06.328 1296-1337/? D/gralloc_ranchu: gralloc_alloc: format 1 and usage 0x900 imply creation of host color buffer

1 个答案:

答案 0 :(得分:0)

根本原因是:

  

引起:android.database.CursorIndexOutOfBoundsException:索引4   请求,大小为4

将索引请求更改为3(最大)。 索引为零。

可能在你的代码的这一行:

String[] from = {AllEmployees.getString(1), AllEmployees.getString(2), AllEmployees.getString(3), AllEmployees.getString(4)};

尝试0到3(输入1到4)。我猜你最多只有四列或者什么。

EDIT 尝试评论更改以下代码(注释我在下面评论的行) 我相信你正在迭代到数据的末尾,所以你的光标在你尝试阅读之前已经过了所有的数据。

AllEmployees.moveToFirst();
      //  while (!AllEmployees.isAfterLast()){
        //    AllEmployees.moveToNext();
       // }

        String[] from = {AllEmployees.getString(1), AllEmployees.getString(2), AllEmployees.getString(3), AllEmployees.getString(4)};
        int [] to = {R.id.tv_fullName, R.id.tv_phoneNum, R.id.tv_jobPosition, R.id.tv_availability};
        ListAdapter adapter = new SimpleCursorAdapter(this, R.layout.item_listview, AllEmployees, from, to, 0);
        ListView myList = (ListView)findViewById(R.id.listView);
        myList.setAdapter(adapter);

编辑2

尝试用我的代码替换你的代码(以下3行):

ListAdapter adapter = new SimpleCursorAdapter(this, R.layout.item_listview, AllEmployees, from, to, 0);
        ListView myList = (ListView)findViewById(R.id.listView);
        myList.setAdapter(adapter);

新代码

  String[]values={"Android","iOS","Windows Phone","Other Stuff"};
            ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, android.R.id.text1,values);
            myList.setAdapter(adapter);

如果一切正常,请在工作代码(将添加数据库中的值)后尝试以下代码:

while (!AllEmployees.isAfterLast()){
               AllEmployees.moveToNext();
               adapter.add(AllEmployees.getString(0);
           }
adapter.notifyDataSetChanged (); // updates the list in UI

仅在另一部分工作后添加此第二部分。 这不完全正确,但在此之后你应该能够解决它。