我有一个字典应用程序,它存储一个含义,类型(英文,中文,日文等)和喜欢的状态(是否是最喜欢的单词)。在我的1个菜单项中,有一个名为sort的项目。当我点击它时,我希望主页中的单词按升序排序,但我在 ListFragment.java 中得到了这个错误:'java.lang.IllegalStateException:couldn从CursorWindow读取第0行,第4列。在从中访问数据之前,请确保Cursor已正确初始化。。我的数据库没有任何问题。
MainActivity.java
package mapp.com.sg.pocketdictionary;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import mapp.com.sg.pocketdictionary.db.WordsDataSource;
public class MainActivity extends AppCompatActivity implements ListFragment.OnContactSelectedInterface/*,SearchView.OnQueryTextListener*/ {
protected WordsDataSource myDataSource;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myDataSource = new WordsDataSource(this);
this.setTitle("PD");
//The code here decides whether to create the fragment because it can be destroyed by the Android system
//when it reclaims memory
ListFragment savedFragment = (ListFragment) getSupportFragmentManager().findFragmentByTag("WORDS_FRAGMENT");
if (savedFragment == null) {
ListFragment fragment = new ListFragment();
Bundle bundle = new Bundle();
bundle.putBoolean("isFavourite", false);
fragment.setArguments(bundle);
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.placeHolder, fragment, "WORDS_FRAGMENT");
fragmentTransaction.commit();
}
}
@Override
protected void onResume() {
//The code here is required because when I save the data and navigate back
//I need my applicationn logic to refresh the fragement content to reflect the changes
//to avoid the list interface listing the old data.
super.onResume();
ListFragment savedFragment = (ListFragment) getSupportFragmentManager().findFragmentByTag("WORDS_FRAGMENT");
if (savedFragment != null) {
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.detach(savedFragment);
fragmentTransaction.attach(savedFragment);
fragmentTransaction.commit();
}
}
@Override
public void onListContactSelected(int index) {
//When tap on a row display word, this logic here will start collecting the
//id which is tied to the data and navigate the user to another Activity
//and at the same time pass the id over.
// Toast.makeText(this, "PUMPKINNNNNN", Toast.LENGTH_SHORT).show(); for testing if tap detected
Intent intent = new Intent(this, WordsDetailActivity.class);
intent.putExtra("WordId", index);//index variable name may not be suitable here
startActivity(intent);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater myMenuInflater = getMenuInflater();
myMenuInflater.inflate(R.menu.menu, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
String itemTitle = item.getTitle().toString();
if (item.getItemId() == R.id.favourite) {
// Toast.makeText(this, "GER" , Toast.LENGTH_SHORT).show();//Go to favorite action choice detected
startActivity(new Intent(this, FavouriteActivity.class));
} else if (item.getItemId() == R.id.Add) {
// Toast.makeText(this, "EEEEYEERR", Toast.LENGTH_SHORT).show();//Go to add word action choice detected
startActivity(new Intent(this, AddWordsActivity.class));
} else if (item.getItemId() == R.id.sort) {
Bundle bundle = new Bundle();
bundle.putBoolean("isSortByAsc", true);
ListFragment savedFragment = (ListFragment) getSupportFragmentManager().findFragmentByTag("WORDS_FRAGMENT");
if (savedFragment != null) {
savedFragment.setArguments(bundle);
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.detach(savedFragment);
fragmentTransaction.attach(savedFragment);
fragmentTransaction.commit();
}
}
}
return super.onOptionsItemSelected(item);
}
}
ListFragment.java
package mapp.com.sg.pocketdictionary;
import android.database.Cursor;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import mapp.com.sg.pocketdictionary.db.WordsDataSource;
public class ListFragment extends Fragment {
protected WordsDataSource mDataSource;
private boolean isFavourite;
private boolean isSortByAsc;
public interface OnContactSelectedInterface {
void onListContactSelected(int index);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
OnContactSelectedInterface listener = (OnContactSelectedInterface) getActivity();
isFavourite = getArguments().getBoolean("isFavourite");
isSortByAsc = getArguments().getBoolean("isSortByAsc");
View view = inflater.inflate(R.layout.fragment_recycler, container,false);
//-------------------
//The rest of the code below is to read all or favorite word data
//and fill up the ArrayList variable.
mDataSource = new WordsDataSource(getContext());
mDataSource.open();
Cursor cursor;
if(isFavourite){
cursor = mDataSource.selectFavouriteWords();
}
else if (isSortByAsc){
cursor = mDataSource.sortWords();
}
else{
cursor = mDataSource.selectAllWords();
}
ArrayList<Words> wordsList = new ArrayList<>();
cursor.moveToFirst();
while(!cursor.isAfterLast()){
boolean tempFav = true;//The database uses 0 and 1 to represent true or false
//Therefore I used this tempFav so that my logic here can store true or false
//during the getString() call
//Error occurs here
if (cursor.getInt(4) != 0) {
tempFav = false;
}
Words tempWords =new Words(cursor.getString(1),cursor.getString(2),cursor.getString(3),tempFav);
tempWords.setId(cursor.getInt(0));
wordsList.add(tempWords);
//Log.d("MY Activity", "onCreateView: "+ tempWords.getId()+" " + tempWords.getWord()+" " +tempWords.getMeaning()+" "+ tempWords.getType()+" "+ cursor.getInt(4));
Log.d("MY Activity", "cursor: "+ cursor.getInt(0)+ " "+cursor.getString(1)+" " + cursor.getString(2)+" "+cursor.getString(3)+" " + cursor.getInt(4));
//Column 0 is id, column 1 is word, column 2 is meaning, column 3 is type, column 4 is favorite status(0 for true and 1 for false)
cursor.moveToNext();
}
mDataSource.close();
//-----------------------
//After the ArrayList variable is filled with data,
//create a listAdapter type object
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
//Creating a ListAdapter object and at the same time pass in a "walkie-talkie" so that it can
//yell out if any related events happening and also the ArrayList of contect information
ListAdapter listAdapter = new ListAdapter(listener, wordsList);
recyclerView.setAdapter(listAdapter);//Start using it
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
return view;
}
}
WordsDataSource.java
package mapp.com.sg.pocketdictionary.db;
//insert update delete
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import mapp.com.sg.pocketdictionary.Words;
public class WordsDataSource {
private SQLiteDatabase mDatabase;
private WordsHelper mWordsHelper;
private Context mContext;
public WordsDataSource(Context context){
mContext = context;
mWordsHelper = new WordsHelper(mContext);
}
//open data base
public void open() throws SQLException {
mDatabase = mWordsHelper.getWritableDatabase();
}
//close
public void close() {
mDatabase.close();
}
//insert
public void insertWords(Words words) {
mDatabase.beginTransaction();
try{
ContentValues values = new ContentValues();
values.put(WordsHelper.COLUMN_WORD, words.getWord());
values.put(WordsHelper.COLUMN_MEANING, words.getMeaning());
values.put(WordsHelper.COLUMN_TYPE, words.getType());
int fav = 0;
if (!words.isFavourite()) {
fav = 1;
}
values.put(WordsHelper.COLUMN_FAVOURITE, fav);
mDatabase.insert(WordsHelper.TABLE_WORDS, null, values);
mDatabase.setTransactionSuccessful();
} finally {
mDatabase.endTransaction();
}
}
//sort
public Cursor sortWords (){
String[] wordname = new String[]{ WordsHelper.COLUMN_WORD };
Cursor cursor= mDatabase.query(WordsHelper.TABLE_WORDS,wordname , null, null, null, null, WordsHelper.COLUMN_WORD+" ASC");
return cursor;
}
//select
public Cursor selectAllWords(){
Cursor cursor = mDatabase.rawQuery("Select * from " + WordsHelper.TABLE_WORDS, null);
return cursor;
}
public Cursor selectOneWord(int Id){
Cursor cursor = mDatabase.rawQuery("Select * from " + WordsHelper.TABLE_WORDS+" where "
+ WordsHelper.COLUMN_ID+" = " + Id, null);
return cursor;
}
public Cursor selectFavouriteWords() {
Cursor cursor = mDatabase.rawQuery("Select * from " + WordsHelper.TABLE_WORDS+" where "
+ WordsHelper.COLUMN_FAVOURITE+" = 0" , null);
return cursor;
}
//update
public boolean updateWords(int id, String word, String meaning,String type, boolean fav){
ContentValues values = new ContentValues();
int success = -1;
values.put(WordsHelper.COLUMN_WORD, word);
values.put(WordsHelper.COLUMN_MEANING, meaning);
values.put(WordsHelper.COLUMN_TYPE, type);
int favDigit = 0;
if(!fav){
favDigit = 1;
}
values.put(WordsHelper.COLUMN_FAVOURITE, favDigit);
success = mDatabase.update(
WordsHelper.TABLE_WORDS,
values,
WordsHelper.COLUMN_ID + " = " + id,
null
);
if(success != -1 && success != 0) {
return true;
} else {
return false;
}
}
public boolean setFavourite (int id, boolean fav) {
ContentValues values = new ContentValues();
int success = -1;
int favDigit = 0;
if(!fav){
favDigit = 1;
}
values.put(WordsHelper.COLUMN_FAVOURITE, favDigit);
success = mDatabase.update(
WordsHelper.TABLE_WORDS,
values,
WordsHelper.COLUMN_ID + " = " + id,
null
);
if(success != -1 && success != 0) {
return true;
} else {
return false;
}
}
public boolean updateWords(int id, String word, String meaning,String type){
ContentValues values = new ContentValues();
int success = -1;
if(word != null ){
values.put(WordsHelper.COLUMN_WORD, word);
}
if(meaning != null ){
values.put(WordsHelper.COLUMN_MEANING, meaning);
}
if(type != null ){
values.put(WordsHelper.COLUMN_TYPE, type);
}
success = mDatabase.update(
WordsHelper.TABLE_WORDS,
values,
WordsHelper.COLUMN_ID + " = " + id,
null
);
if(success != -1 && success != 0) {
return true;
} else {
return false;
}
}
//delete
public boolean deleteWords(int id) {
int success = -1;
success = mDatabase.delete(
WordsHelper.TABLE_WORDS,
WordsHelper.COLUMN_ID + " = " + id,
null
);
if(success != -1 && success !=0) {
return true;
} else {
return false;
}
}
public boolean deleteWords() {
int success = -1;
success = mDatabase.delete(
WordsHelper.TABLE_WORDS,
null,
null
);
if(success != -1 ) {
return true;
} else {
return false;
}
}
}
WordsHelper.java
package mapp.com.sg.pocketdictionary.db;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
//Helps make all code in WordsDataSource neater, readable and maintainable.
public class WordsHelper extends SQLiteOpenHelper {
public static final String TABLE_WORDS ="WORDS";
public static final String COLUMN_ID = "_ID";
public static final String COLUMN_WORD = "WORD";
public static final String COLUMN_MEANING = "MEANING";
public static final String COLUMN_TYPE = "TYPE";
public static final String COLUMN_FAVOURITE = "FAVOURITE";
private static final String DB_NAME = "words.db";
private static final int DB_VER = 1;
private static final String DB_CREATE = "CREATE TABLE "+TABLE_WORDS+
" (" + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT" +
", " + COLUMN_WORD + " TEXT, " +
COLUMN_MEANING + " TEXT,"+
COLUMN_TYPE + " TEXT,"+ COLUMN_FAVOURITE +" INTEGER)";
public WordsHelper(Context context){
super(context, DB_NAME, null, DB_VER);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(DB_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
答案 0 :(得分:1)
当您尝试阅读数据时,您需要获得ReadableDatabase
,但您的开放始终会获得WritableDatabase
,如
主要代码
mDataSource = new WordsDataSource(getContext());
mDataSource.openforRead(); // <-- will return readable database
Cursor cursor;
if(isFavourite){
cursor = mDataSource.selectFavouriteWords();
}
else if (isSortByAsc){
cursor = mDataSource.sortWords();
}
else{
cursor = mDataSource.selectAllWords();
}
ArrayList<Words> wordsList = new ArrayList<>();
cursor.moveToFirst();
while(!cursor.isAfterLast()){
boolean tempFav = true;//The database uses 0 and 1 to represent true or false
//Therefore I used this tempFav so that my logic here can store true or false
//during the getString() call
//Error occurs here
if (cursor.getInt(cursor.getColumnIndex(WordsHelper.COLUMN_FAVOURITE)) != 0) {
tempFav = false;
}
Words tempWords =new Words(cursor.getString(1),cursor.getString(2),cursor.getString(3),tempFav);
tempWords.setId(cursor.getInt(0));
wordsList.add(tempWords);
//Log.d("MY Activity", "onCreateView: "+ tempWords.getId()+" " + tempWords.getWord()+" " +tempWords.getMeaning()+" "+ tempWords.getType()+" "+ cursor.getInt(4));
Log.d("MY Activity", "cursor: "+ cursor.getInt(0)+ " "+cursor.getString(1)+" " + cursor.getString(2)+" "+cursor.getString(3)+" " + cursor.getInt(4));
//Column 0 is id, column 1 is word, column 2 is meaning, column 3 is type, column 4 is favorite status(0 for true and 1 for false)
cursor.moveToNext();
}
将以下方法添加到WordsDataSource
public void openForRead() throws SQLException {
mDatabase = mWordsHelper.getReadableDatabase();
}
答案 1 :(得分:0)
如果您尝试访问
int value=cursor.getInt(4)
它有空值或超出整数范围会引发异常。
对于这种情况尝试下面的代码
if ( !cursor.isNull( columnIndex ) )
{
value = cursor.getInt( columnIndex );
}
else
{
value=0; //default value
}
出于调试目的,首先使用下面的代码
检查光标的值Log.d("CursorObject", DatabaseUtils.dumpCursorToString(cursor))