Android 在sqlite数据库的recyclerview中设置数据时发生IndexAutofBound异常

Android 在sqlite数据库的recyclerview中设置数据时发生IndexAutofBound异常,android,xml,android-fragments,android-recyclerview,android-sqlite,Android,Xml,Android Fragments,Android Recyclerview,Android Sqlite,我从sqlite获取数据并将其填充到recyclerview中,但在填充数据的同时,我在我的logcat中获得IndexOutOfBoundException。 有人能告诉我为什么我会得到这个例外吗 Databasehelper类代码: public class DatabaseHelper extends SQLiteOpenHelper { public static final String DATABASE_NAME = "history.db"; public static fina

我从sqlite获取数据并将其填充到recyclerview中,但在填充数据的同时,我在我的logcat中获得IndexOutOfBoundException。 有人能告诉我为什么我会得到这个例外吗

Databasehelper类代码:

public class DatabaseHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "history.db";
public  static final String TABLE_NAME = "history_table";
public static  final String COL_1 = "ID";
public static  final String COL_2 = "URL";
public  static final String COL_3 = "TITLE";
public DatabaseHelper(@Nullable Context context) {
    super(context, DATABASE_NAME, null, 1);
    SQLiteDatabase db = this.getWritableDatabase();
}

@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL("CREATE TABLE "+ TABLE_NAME+"(ID INTEGER PRIMARY KEY AUTOINCREMENT, URL TEXT, TITLE TEXT)");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS "+TABLE_NAME);
    onCreate(db);
}
public  boolean insertData(String url, String title){
    SQLiteDatabase db = this.getWritableDatabase();
    ContentValues contentValues = new ContentValues();
    contentValues.put(COL_2, url);
    contentValues.put(COL_3, title);
    long result = db.insert(TABLE_NAME,null,contentValues);
    if(result == -1) {
        return false;
    }
    else{
        return true;
    }

}
public  boolean updateData(String id, String url, String title) {
    SQLiteDatabase db = this.getWritableDatabase();
    ContentValues contentValue= new ContentValues();
    contentValue.put(COL_1, id);
    contentValue.put(COL_2, url);
    contentValue.put(COL_3, title);
    db.update(TABLE_NAME, contentValue, "ID= ?",new String[]{id} );
    return true;
}
public Cursor getalldata() {
    SQLiteDatabase db = this.getWritableDatabase();
    Cursor res = db.rawQuery("select * from "+ TABLE_NAME, null);
    return res;
}
public Cursor getuniquedata(String id){
    SQLiteDatabase db = this.getWritableDatabase();
    Cursor res = db.rawQuery("select * from "+ TABLE_NAME+" where " +COL_2+" = ?", new String []{id});
    return res;
}
public void deletedata(String id){
    SQLiteDatabase db = this.getWritableDatabase();
    db.delete(TABLE_NAME, COL_2+ "= ?", new String []{id});
} }

在模型中填充数据并设置适配器时的代码:

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    view =  inflater.inflate(R.layout.fragment_history, container, false);
    button = (Button) view.findViewById(R.id.button1);
    recyclerView = (RecyclerView) view.findViewById(R.id.recyclerview8);
    historyModels = new ArrayList<>();
    LinearLayoutManager mainlayout= new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL,false);
    recyclerView.setLayoutManager(mainlayout);
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    mydb = new DatabaseHelper(getContext());
    Cursor res = mydb.getalldata();
    res.moveToFirst();
    if(res!=null) {
            while (res.moveToNext()) ;
            {
                HistoryModel historyModel = new HistoryModel(res.getString(1), res.getString(2));  //this line is giving error
                historyModels.add(historyModel);
            }
        mydb.close();
        historyRecyclerAdapter = new HistoryRecyclerAdapter(historyModels, getContext());
        recyclerView.setAdapter(historyRecyclerAdapter);
    }
    return view;
}
日志错误:

android.database.CursorIndexOutOfBoundsException: Index 8 requested, with a size of 8
    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.haryanvigaane.Fragment.HistoryFragment.onCreateView(HistoryFragment.java:77)
    at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2600)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:881)
    at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
    at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439)
    at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
    at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
    at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
    at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1727)

首先是这一行:

res.moveToFirst();
光标的索引移动到第一行
然后开始一个空循环:

while (res.moveToNext());
因为末尾有分号,即使您删除了它,您创建的列表也会错过第一行。
在这个空循环之后,它只推进
光标的索引,并最终在
光标的最后一行之后设置,在花括号内的以下代码块中(这不是
while
)尝试检索两列的值,这就是引发错误的地方,因为
光标的索引所在的位置没有行。
将代码更改为:

Cursor res = mydb.getalldata();
while (res.moveToNext()) {
    HistoryModel historyModel = new HistoryModel(res.getString(1), res.getString(2));     
    historyModels.add(historyModel);
}
res.close();
mydb.close();
historyRecyclerAdapter = new HistoryRecyclerAdapter(historyModels, getContext());
recyclerView.setAdapter(historyRecyclerAdapter);
请注意,使用
getColumnIndex()
而不是显式设置列的索引是一种很好的做法,因此我建议:

HistoryModel historyModel = new HistoryModel(
    res.getString(res.getColumnIndex(DatabaseHelper.URL)), 
    res.getString(res.getColumnIndex(DatabaseHelper.TITLE))
);

我猜它是在迭代最后一个元素时出现的,所以只需更改while to-do{//your logic}while(res.moveToNext());伟大的它工作正常,所有数据都正常。非常感谢您,是的,我会记得在以后的项目中使用getColumnIndex()。
HistoryModel historyModel = new HistoryModel(
    res.getString(res.getColumnIndex(DatabaseHelper.URL)), 
    res.getString(res.getColumnIndex(DatabaseHelper.TITLE))
);