我的问题:
在我的项目中,我有一个sqlite数据库。我尝试在另一个项目中测试这些相同的类(Database Handler类和helper class-Hitlist.java),执行简单的操作,例如添加到数据库,获取计数,获取数据库中所有行的列表,并且它工作得很好。但是在这个带有viewpager的项目中,每个页面都从数据库中提取数据,当我的视图寻呼机适配器从数据库中请求一行时,会出现此错误。我在StackOverflow上看到了很多关于类似标题的问题,但没有一个能解决我的问题。
logcat:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.rohan.hitlistofarya/com.rohan.hitlistofarya.MainActivity}: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2456)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2539)
at android.app.ActivityThread.access$900(ActivityThread.java:159)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1384)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:152)
at android.app.ActivityThread.main(ActivityThread.java:5507)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
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.rohan.hitlistofarya.DBHandler.getPerson(DBHandler.java:102)
at com.rohan.hitlistofarya.VpagerAdapter.getPageTitle(VpagerAdapter.java:40)
at android.support.design.widget.TabLayout.populateFromPagerAdapter(TabLayout.java:903)
at android.support.design.widget.TabLayout.setPagerAdapter(TabLayout.java:894)
at android.support.design.widget.TabLayout.setupWithViewPager(TabLayout.java:807)
at android.support.design.widget.TabLayout.setupWithViewPager(TabLayout.java:768)
at android.support.design.widget.TabLayout.setupWithViewPager(TabLayout.java:746)
at com.rohan.hitlistofarya.MainFragment.onCreateView(MainFragment.java:48)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2080)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1108)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1290)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1677)
at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:388)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:604)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1277)
at android.app.Activity.performStart(Activity.java:6321)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2419)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2539)
at android.app.ActivityThread.access$900(ActivityThread.java:159)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1384)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:152)
at android.app.ActivityThread.main(ActivityThread.java:5507)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
DBHandler类:
public class DBHandler extends SQLiteOpenHelper {
private static DBHandler sInstance;
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "hitlist";
private static final String TABLE_NAME = "hitlistOfArya";
private static final String COLUMN_ID = "id";
private static final String COLUMN_NAME = "name";
private static final String COLUMN_REASON = "reason";
private static final String COLUMN_STATUS="dead";
private static final String COLUMN_FATE="fate";
private static final String COLUMN_HOUSE="allegiance";
private static final String COLUMN_EXTRA="extra";
private static final String COLUMN_IMG="image";
private DBHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public static synchronized DBHandler getInstance(Context context) {
if (sInstance == null) {
sInstance = new DBHandler(context.getApplicationContext());
}
return sInstance;
}
@Override
public void onCreate(SQLiteDatabase db) {
String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_NAME + "("
+ COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ COLUMN_NAME + " TEXT,"
+ COLUMN_REASON + " TEXT,"
+ COLUMN_STATUS + " INTEGER,"
+ COLUMN_FATE + " TEXT,"
+ COLUMN_HOUSE + " TEXT,"
+ COLUMN_EXTRA + " TEXT,"
+ COLUMN_IMG + " TEXT" + ")";
db.execSQL(CREATE_CONTACTS_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Drop older table if existed
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
// Create tables again
onCreate(db);
}
public void addPerson(Hitlist person) {
SQLiteDatabase db = this.getWritableDatabase();
int dead=person.isDead()?1:0;
ContentValues values = new ContentValues();
values.put(COLUMN_NAME, person.getName());
values.put(COLUMN_REASON, person.getReason());
values.put(COLUMN_STATUS,dead);
values.put(COLUMN_FATE, person.getFate());
values.put(COLUMN_HOUSE, person.getAllegiance());
values.put(COLUMN_EXTRA, person.getExtra());
values.put(COLUMN_IMG, person.getImg());
// Inserting Row
db.insert(TABLE_NAME, null, values);
db.close(); // Closing database connection
}
Hitlist getPerson(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Hitlist person=null;
Cursor cursor = db.query(
TABLE_NAME,
new String[] { COLUMN_ID, COLUMN_NAME, COLUMN_REASON, COLUMN_STATUS, COLUMN_FATE, COLUMN_HOUSE, COLUMN_EXTRA, COLUMN_IMG },
COLUMN_ID + "=?",
new String[] { String.valueOf(id) }, null, null, null, null);
if (cursor != null){
cursor.moveToFirst();
//*************************
boolean dead=(Integer.parseInt(cursor.getString(3))==0)?false:true;//DBHandler line number-102
person = new Hitlist(Integer.parseInt(cursor.getString(0)),
cursor.getString(1), cursor.getString(2), dead,
cursor.getString(4), cursor.getString(5),
cursor.getString(6), cursor.getString(7));
}
return person;
}
public List<Hitlist> getAllPerssons() {
List<Hitlist> persons = new ArrayList<Hitlist>();
String selectQuery = "SELECT * FROM "+TABLE_NAME;
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(selectQuery, null);
Hitlist person;
if (cursor.moveToFirst()) {
do {
person = new Hitlist();
person.setId(Integer.parseInt(cursor.getString(0)));
person.setName(cursor.getString(1));
person.setReason(cursor.getString(2));
boolean dead= (Integer.parseInt(cursor.getString(3))==0)?false:true;
person.setDead(dead);
person.setFate(cursor.getString(4));
person.setAllegiance(cursor.getString(5));
person.setExtra(cursor.getString(6));
person.setImg(cursor.getString(7));
persons.add(person);
} while (cursor.moveToNext());
}
db.close();
return persons;
}
public int editPerson(Hitlist person) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_NAME, person.getName());
values.put(COLUMN_REASON, person.getReason());
values.put(COLUMN_STATUS,person.isDead());
values.put(COLUMN_FATE, person.getFate());
values.put(COLUMN_HOUSE, person.getAllegiance());
values.put(COLUMN_EXTRA, person.getExtra());
values.put(COLUMN_IMG, person.getImg());
// updating row
return db.update(TABLE_NAME, values, COLUMN_ID + " = ?",
new String[] { String.valueOf(person.getId()) });
}
}
VpagerAdapter类:
public class VpagerAdapter extends SmartFragmentStatePagerAdapter {
private int pages=2;
private DBHandler myDB;
public VpagerAdapter(FragmentManager fm, DBHandler myDB){
super(fm);
this.myDB=myDB;
}
public int getPages() {
return pages;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
@Override
public Fragment getItem(int position) {
return fragment1.newInstance(position);
}
public void changePages(){pages++;}
@Override
public int getCount() {
return pages;
}
@Override
public CharSequence getPageTitle(int position) {
//***************************************
return myDB.getPerson(position).getName();//This line 40 is showing error
}
}
MainFragment类:
public class MainFragment extends Fragment{
private ViewPager mPager;
private VpagerAdapter mAdapter;
static DBHandler myDB;
static Hitlist person=new Hitlist();
TabLayout myTabs;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myDB=DBHandler.getInstance(getActivity());
if(myDB.getPersonsCount()==0){
person=new Hitlist("Shruti","XYZ",false,null,null,null,"@drawable/arya");
myDB.addPerson(person);
person=new Hitlist("Rohan","TUV",false,null,null,null,"@drawable/arya2");
myDB.addPerson(person);
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view=inflater.inflate(R.layout.main_fragment,container,false);
mPager= (ViewPager) view.findViewById(R.id.ViewPager);
mPager.setPageTransformer(true,new CubeOutTransformer());
mAdapter=new VpagerAdapter(getActivity().getSupportFragmentManager(),myDB);
mPager.setAdapter(mAdapter);
myTabs= (TabLayout) view.findViewById(R.id.my_tabs);
//********************************
myTabs.setupWithViewPager(mPager);//MainFragment line no.48
return view;
}
}
我已经通过旁边的注释指定了哪些行在课堂上显示错误。
我已在 MainActivity.java 中初始化了我的DBHandler实例,并建议this page。
//In MainActivity.java, onCreate method()
myDB=DBHandler.getInstance(this);
修改 -
我刚才注意到,如果我在MainActivity中调用myDB.getPerson(int id),它可以正常工作。然后同样的错误来自于在fragment1中调用getPerson()(提供给viewpager的片段)。当我在MainActivity中调用getPerson()时,我还将数据添加到MainActivity的onCreate
为什么会这样?数据库实例应该在任何地方都相同。是什么改变了让应用程序崩溃?
修改#2 - 我还尝试在MainFragment类中调用getPerson(),它仍然没有显示光标超出范围的错误。我不知道为什么会发生这种情况.. MainFragment中的getPerson()显然在myTabs.setupWithViewPager(mPager)行之前被调用
欢迎所有建议。谢谢!
解 -
问题出在viewpager的getPageTitle()方法中。我将位置传递给方法getPerson(),该方法采用整数&#34; ID&#34;作为参数。 ID被索引为1而位置被索引为0.只需传递&#34;位置+ 1&#34;而不是&#34;位置&#34; 到getPageTitle()的方法调用解决了我的问题。所以,我的光标不是null它是空的,getPerson()中的查询没有失败,只是查询中没有行,我试图访问它。
答案 0 :(得分:1)
如果从Fragment初始化DBHandler,请使用
myDB=DBHandler.getInstance(getActivity());
在 getPerson(int id)方法中使用如下
if (cursor != null) {
if (cursor.moveToFirst()) {
boolean dead=(Integer.parseInt(cursor.getString(3))==0)?false:true;
Hitlist person = new Hitlist(Integer.parseInt(cursor.getString(0)),
cursor.getString(1), cursor.getString(2), dead,
cursor.getString(4), cursor.getString(5),
cursor.getString(6), cursor.getString(7));
return person;
}
}
希望它能奏效。
答案 1 :(得分:1)
<强> android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
强>
这意味着, Cursor
要么 null ,要么为空即0 rows 。
Hitlist getPerson(int id) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(
TABLE_NAME,
new String[] { COLUMN_ID, COLUMN_NAME, COLUMN_REASON, COLUMN_STATUS,
COLUMN_FATE, COLUMN_HOUSE, COLUMN_EXTRA, COLUMN_IMG },
COLUMN_ID + "=?",
new String[] { String.valueOf(id) }, null, null, null, null);
//Edit Part
if (cursor != null && cursor.getCount()>0) {//perform operations on cursor only when
//it is neither Null nor empty
//another thing, you should check if moveToFirst() returns something or not
Hitlist person;
if (cursor.moveToFirst()) { //now here fetch things from cursor
boolean dead=(Integer.parseInt(cursor.getString(3))==0)?false:true;
person = new Hitlist(Integer.parseInt(cursor.getString(0)),
cursor.getString(1), cursor.getString(2), dead,
cursor.getString(4), cursor.getString(5),
cursor.getString(6), cursor.getString(7));
cursor.close();
return person;
} else {
cursor.close();
//print some message via Snackbar or Toast
}
} else { throw new Exception(); }
cursor.close();
throw new Exception();
}