I want to make a listview of some details,it needs to print out the details that are entered.error:Couldn't read row 0, col -1 from CursorWindow
I want to make a listview of some details,it needs to print out the details that are entered.error:Couldn't read row 0, col -1 from CursorWindow
原因:java.lang.IllegalStateException:无法从 CursorWindow 读取第 0 行,第 -1 列。在从游标访问数据之前,确保游标已正确初始化。
我在 android 清单中将 android:allowBackup="true" 更改为 "False"。
public class ListViewActivity extends Activity {
SQLiteHelper SQLITEHELPER;
SQLiteDatabase SQLITEDATABASE;
Cursor cursor;
SQLiteListAdapter ListAdapter;
ArrayList<String> CODE_ArrayList = new ArrayList<String>();
ArrayList<String> ITEM_ArrayList = new ArrayList<String>();
ArrayList<String> QUANTITY_ArrayList = new ArrayList<String>();
ArrayList<String> TAX_ArrayList = new ArrayList<String>();
ArrayList<String> UNITPRICE_ArrayList = new ArrayList<String>();
ArrayList<String> TOTALPRICE_ArrayList = new ArrayList<String>();
ArrayList<String> SELLER_ArrayList = new ArrayList<String>();
ListView LISTVIEW;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_view);
LISTVIEW = (ListView)findViewById(R.id.listView1);
SQLITEHELPER = new SQLiteHelper(this);
}
@Override
protected void onResume() {
ShowSQLiteDBdata();
super.onResume();
}
private void ShowSQLiteDBdata() {
SQLITEDATABASE = SQLITEHELPER.getWritableDatabase();
cursor = SQLITEDATABASE.rawQuery("SELECT * FROM demoTableb", null);
CODE_ArrayList.clear();
ITEM_ArrayList.clear();
QUANTITY_ArrayList.clear();
TAX_ArrayList.clear();
UNITPRICE_ArrayList.clear();
TOTALPRICE_ArrayList.clear();
SELLER_ArrayList.clear();
if (cursor.moveToFirst()) {
do {
CODE_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Codes)));
ITEM_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Item)));
QUANTITY_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Quantity)));
TAX_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Tax)));
UNITPRICE_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Unitprice)));
TOTALPRICE_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Totalprice)));
SELLER_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Seller)));
} while (cursor.moveToNext());
}
ListAdapter = new SQLiteListAdapter(ListViewActivity.this,
CODE_ArrayList,
ITEM_ArrayList,
QUANTITY_ArrayList,
TAX_ArrayList,
UNITPRICE_ArrayList,
TOTALPRICE_ArrayList,
SELLER_ArrayList
);
LISTVIEW.setAdapter(ListAdapter);
cursor.close();
}
}
- 错误显示在行
ShowSQLiteDBdata();
和 SQLITEDATABASE = SQLITEHELPER.getWritableDatabase();
这是 EditDataActivity
public class EditDataActivity extends Activity {
Button next, previous, update, delete;
EditText item,quantity,tax,unitprice,totalprice,seller;
SQLiteDatabase SQLITEDATABASE, SQLITEDATABASE2;
String GetSQliteQuery, UpdateRecordQuery, DeleteQuery ;
Cursor cursor, cursorCheckDataIsEmptyOrNot ;
TextView purchase;
Boolean CheckEditTextEmpty;
String Item,Quantity,Tax,Unitprice,Totalprice,Seller;
int ItemCode ;
String ConvertCode ;
SQLiteHelper SQLITEHELPER;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_data);
next = (Button)findViewById(R.id.button1);
previous = (Button)findViewById(R.id.button2);
update = (Button)findViewById(R.id.button3);
delete = (Button)findViewById(R.id.button4);
item = (EditText)findViewById(R.id.editText2);
quantity = (EditText)findViewById(R.id.editText3);
tax = (EditText)findViewById(R.id.editText4);
unitprice = (EditText)findViewById(R.id.editText5);
totalprice = (EditText)findViewById(R.id.editText6);
seller = (EditText)findViewById(R.id.editText7);
purchase = (TextView)findViewById(R.id.textview1);
GetSQliteQuery = "SELECT * FROM demoTableb" ;
SQLITEDATABASE = openOrCreateDatabase("DemoDataBaseb", Context.MODE_PRIVATE, null);
cursor = SQLITEDATABASE.rawQuery(GetSQliteQuery, null);
cursor.moveToFirst();
GetSQLiteDatabaseRecords();
next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (!cursor.isLast()){
cursor.moveToNext();
}
GetSQLiteDatabaseRecords();
}
});
previous.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (!cursor.isFirst()){
cursor.moveToPrevious();
}
GetSQLiteDatabaseRecords();
}
});
update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Item = item.getText().toString();
Quantity = quantity.getText().toString();
Tax = tax.getText().toString();
Unitprice = unitprice.getText().toString();
Totalprice = totalprice.getText().toString();
Seller = seller.getText().toString();
ConvertCode = purchase.getText().toString();
ItemCode = Integer.parseInt(ConvertCode);
UpdateRecordQuery = "UPDATE demoTableb SET Item ='" + Item + "', Quantity ='" + Quantity + "' ,Tax = '"+Tax+"',Unitprice = '"+Unitprice+"',Totalprice = '"+Totalprice+"',Seller ='"+Seller+"' WHERE Code=" + ItemCode + ";";
CheckEditTextIsEmptyOrNot(Item,Quantity,Tax,Unitprice,Totalprice,Seller );
if (CheckEditTextEmpty == false) {
SQLITEDATABASE.execSQL(UpdateRecordQuery);
cursor = SQLITEDATABASE.rawQuery(GetSQliteQuery, null);
cursor.moveToPosition(ItemCode);
Toast.makeText(EditDataActivity.this,"Data Updated Successfully", Toast.LENGTH_LONG).show();
}else {
Toast.makeText(EditDataActivity.this,"Please Fill All the Fields", Toast.LENGTH_LONG).show();
}
}
});
delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
ConvertCode = purchase.getText().toString();
ItemCode = Integer.parseInt(ConvertCode);
DeleteQuery = "DELETE FROM demoTableb WHERE Code=" + ItemCode + ";";
SQLITEDATABASE.execSQL(DeleteQuery);
Toast.makeText(EditDataActivity.this, "Record Deleted Successfully", Toast.LENGTH_LONG).show();
cursor = SQLITEDATABASE.rawQuery(GetSQliteQuery, null);
}
});
}
public void GetSQLiteDatabaseRecords(){
purchase.setText(cursor.getString(0).toString());
item.setText(cursor.getString(1).toString());
quantity.setText(cursor.getString(2).toString());
tax.setText(cursor.getString(3).toString());
unitprice.setText(cursor.getString(4).toString());
totalprice.setText(cursor.getString(5).toString());
seller.setText(cursor.getString(6).toString());
}
public void CheckEditTextIsEmptyOrNot (String Item, String Quantity, String Tax, String Unitprice, String Totalprice,String Seller){
if( TextUtils.isEmpty(Item) || TextUtils.isEmpty(Quantity)|| TextUtils.isEmpty(Tax)|| TextUtils.isEmpty(Unitprice)|| TextUtils.isEmpty(Totalprice) || TextUtils.isEmpty(Seller)){
CheckEditTextEmpty = true ;
}
else {
CheckEditTextEmpty = false ;
}
}
}
这是主要活动
public class SecondActivity extends Activity {
EditText code,item,quantity,tax,unitprice,totalprice,seller ;
Button Submit, EditData, DisplayData;
SQLiteDatabase SQLITEDATABASE;
String Codes,Item,Quantity,Tax,Unitprice,Totalprice,Seller ;
Boolean CheckEditTextEmpty ;
String SQLiteQuery ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.purchase);
code = (EditText)findViewById(R.id.edtcd);
item = (EditText)findViewById(R.id.edtitm);
quantity= (EditText)findViewById(R.id.edtqty);
tax = (EditText) findViewById(R.id.edttax);
unitprice = (EditText) findViewById(R.id.edtprc);
totalprice = (EditText) findViewById(R.id.edttp);
seller = (EditText) findViewById(R.id.edtslr);
Submit = (Button)findViewById(R.id.sbt);
EditData = (Button)findViewById(R.id.edt);
DisplayData = (Button)findViewById(R.id.dply);
Submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
DBCreate();
SubmitData2SQLiteDB();
}
});
EditData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent i=new Intent(getApplicationContext(),EditDataActivity.class);
startActivity(i);
}
});
DisplayData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent i=new Intent(SecondActivity.this,ListViewActivity.class);
startActivity(i);
}
});
}
public void DBCreate(){
SQLITEDATABASE = openOrCreateDatabase("DemoDataBaseb", Context.MODE_PRIVATE, null);
SQLITEDATABASE.execSQL("CREATE TABLE IF NOT EXISTS demoTableb(Code INTEGER PRIMARY KEY , item INTEGER,quantity INTEGER, tax INTEGER,Unitprice INTEGER,Totalprice INTEGER,Seller VARCHAR);");
}
public void SubmitData2SQLiteDB(){
Codes = code.getText().toString();
Item = item.getText().toString();
Quantity = quantity.getText().toString();
Tax = tax.getText().toString();
Unitprice = unitprice.getText().toString();
Totalprice = totalprice.getText().toString();
Seller = seller.getText().toString();
CheckEditTextIsEmptyOrNot( Codes,Item,Quantity,Tax,Unitprice,Totalprice,Seller);
if(CheckEditTextEmpty == true)
{
SQLiteQuery = "INSERT INTO demoTableb (code,item,quantity,tax,unitprice,totalprice,seller) VALUES('"+Codes+"', '"+Item+"','"+Quantity+"','"+Tax+"','"+Unitprice+"','"+Totalprice+"', '"+Seller+"');";
SQLITEDATABASE.execSQL(SQLiteQuery);
Toast.makeText(SecondActivity.this,"Data Submit Successfully", Toast.LENGTH_LONG).show();
ClearEditTextAfterDoneTask();
}
else {
Toast.makeText(SecondActivity.this,"Please Fill All the Fields", Toast.LENGTH_LONG).show();
}
}
public void CheckEditTextIsEmptyOrNot(String code, String item, String quantity, String tax, String Name, String PhoneNumber, String subject){
if(TextUtils.isEmpty(Codes) || TextUtils.isEmpty(Item) || TextUtils.isEmpty(Quantity) || TextUtils.isEmpty(Tax) || TextUtils.isEmpty(Unitprice) || TextUtils.isEmpty(Totalprice) || TextUtils.isEmpty(Seller)){
CheckEditTextEmpty = false ;
}
else {
CheckEditTextEmpty = true ;
}
}
public void ClearEditTextAfterDoneTask(){
code.getText().clear();
item.getText().clear();
quantity.getText().clear();
tax.getText().clear();
unitprice.getText().clear();
totalprice.getText().clear();
seller.getText().clear();
}
}
public class SQLiteHelper extends SQLiteOpenHelper {
static String DATABASE_NAME="DemoDataBaseb";
public static final String Codes="code";
public static final String TABLE_NAME="demoTableb";
public static final String Item="itm";
public static final String Quantity="qty";
public static final String Tax="tax";
public static final String Unitprice="prc";
public static final String Totalprice="tp";
public static final String Seller="slr";
public SQLiteHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
}
@Override
public void onCreate(SQLiteDatabase database) {
String CREATE_TABLE="CREATE TABLE IF NOT EXISTS "+TABLE_NAME+" ("+Codes+" INTEGER PRIMARY KEY, "+Item+" VARCHAR, "+Quantity+" INTEGER, "+Tax+" INTEGER,"+Unitprice+" INTEGER,"+Totalprice+" INTEGER,"+Seller+" VARCHAR )";
database.execSQL(CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS "+TABLE_NAME);
onCreate(db);
}
}
额外错误
public class MainActivity 扩展 AppCompatActivity {
SuggestedSQLiteHelper dbHelper;
Cursor cursor;
SimpleCursorAdapter sca;
ListView listview1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new SuggestedSQLiteHelper(this);
listview1 = this.findViewById(R.id.listView1);
if (dbHelper.isTableEmpty(SuggestedSQLiteHelper.TABLE_NAME)) {
dbHelper.insertDemoTablebRow("Item1",1,5,100,100,"Fred");
}
setOrRefreshListView();
}
private void setOrRefreshListView() {
cursor = dbHelper.getAllFromDemoTableb();
if (sca == null) {
// setup the adapter
// NOTE CURSOR ADAPTERS MUST HAVE _ID column which MUST be type INTEGER and UNIQUE
// see use of BaseColumns._ID in table create
sca = new SimpleCursorAdapter(this,R.layout.demotableb_layout,cursor,
// The columns FROM which the data is to be retrieved
new String[]{
SuggestedSQLiteHelper.ITEM_COLUMN,
SuggestedSQLiteHelper.QUANTITY_COLUMN,
SuggestedSQLiteHelper.TAX_COLUMN,
SuggestedSQLiteHelper.UNITPRICE_COLUMN,
SuggestedSQLiteHelper.TOTALPRICE_COLUMN,
SuggestedSQLiteHelper.SELLER_COLUMN
},
// The id of the view's to display the data as per the layout (2nd parm)
new int[]{
R.id.item,
R.id.quantity,
R.id.tax,
R.id.unitprice,
R.id.totalprice,
R.id.seller
},0 // 0 is fine
);
listview1.setAdapter(sca); // Tie the adapter to the ListView
// Can add the Listeners here e.g.
listview1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
// DO SOMETHING HERE NOTING
// long l passed (4th parm) is the _id of the clicked item
// hence l can be passed/used as it uniquely identifies the row
// e.g.
Cursor csr = dbHelper.getDemotablebById(l);
DatabaseUtils.dumpCursor(csr);
csr.close();
}
});
} else {
sca.swapCursor(cursor);
}
}
@Override
protected void onResume() {
super.onResume();
setOrRefreshListView(); //<<<<<<<<<< will refresh the listview in case data has changed
}
@Override
protected void onDestroy() {
cursor.close(); //<<<<<<<<< should always close the cursor when done with it
super.onDestroy();
}
}
错误
原因:java.lang.NullPointerException:尝试在空对象引用上调用虚方法 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)'
在 com.allmycode.stac.MainActivity.setOrRefreshListView(MainActivity.java:69)
在 com.allmycode.stac.MainActivity.onCreate(MainActivity.java:40)
问题是 getColumnIndex
方法,如果传递了游标中不存在的列名 returns - 1 根据 :-
Returns the zero-based index for the given column name, or -1 if the column doesn't exist. If you expect the column to exist use getColumnIndexOrThrow(java.lang.String) instead, which will make the error more clear. https://developer.android.com/reference/android/database/Cursor#getColumnIndex(java.lang.String)
因为 Cursor 中不存在这样一个预期的列,并且当您使用 SELECT * ....
时,该列不存在于 table demoTableb.
您需要检查 table 和提取的列是否兼容。那就是将缺失的列添加到 table 或从从游标中提取的列中删除缺失的列。
注意 我相信 getColumnIndex
有一个错误,因为它(曾经)区分大小写(过去肯定是)所以问题可能是列名
如果您不确定,那么转储 Cursor 可能会有所帮助。例如你可以使用:-
cursor = SQLITEDATABASE.rawQuery("SELECT * FROM demoTableb", null);
DatabaseUtils.dumpCursor(cursor); //<<<<<<<<<< Will dump the cursor to the log.
这里有一个被丢弃的 Cursor 的例子:-
09-30 08:25:57.238 1933-1933/so52573525.so52573525 D/ADDRESULT: Added row
09-30 08:25:57.238 1933-1933/so52573525.so52573525 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@456d67
0 {
SEM_ID=1
Date=2018-09-01
Department=Area 1
Topic=Blah
Speaker=Fred
No_of_Students=10
Guests=Tom
Organisation=The org
}
1 {
SEM_ID=2
Date=2018-08-01
Department=Area 2
Topic=Another
Speaker=Mary
No_of_Students=100
Guests=Sue, Tom and Anne
Organisation=Acme
}
<<<<<
从转储中您可以看到 Cursor 中的列是:-
- SEM_ID
- 日期
- 部门
- 话题
- 演讲者
- No_of_Students
- 来宾
- 组织
您还可以看到第 0 行和第 1 行已被提取。
附加 评论:-
i uninstalled and reinstalled it but listview doesn't display.i uploaded th SQLiteHelper above could you pls correct it.
我相信卸载和重新安装可以让您继续前进,也就是说您似乎更改了 table 以添加一列,然后 col -1
被固定为 table 随后被更改,因此该列现在存在。
当然,您的代码的本质是有效的。为了证明它确实有效,我使用您的 SQLiteHelper class 组装了一个测试应用程序,没有任何更改,然后从您的 ListViewActivity 并根据 :-
将其放入 activity (MainActivity)
public class MainActivity extends AppCompatActivity {
SQLiteHelper SQLITEHELPER;
SQLiteDatabase SQLITEDATABASE;
Cursor cursor;
//SQLiteListAdapter ListAdapter;
ArrayList<String> CODE_ArrayList = new ArrayList<String>();
ArrayList<String> ITEM_ArrayList = new ArrayList<String>();
ArrayList<String> QUANTITY_ArrayList = new ArrayList<String>();
ArrayList<String> TAX_ArrayList = new ArrayList<String>();
ArrayList<String> UNITPRICE_ArrayList = new ArrayList<String>();
ArrayList<String> TOTALPRICE_ArrayList = new ArrayList<String>();
ArrayList<String> SELLER_ArrayList = new ArrayList<String>();
ListView LISTVIEW;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SQLITEHELPER = new SQLiteHelper(this);
SQLITEDATABASE = SQLITEHELPER.getWritableDatabase();
/* ADDED to insert a row ino the table */
ContentValues cv = new ContentValues();
cv.put(SQLiteHelper.Item,"Item1");
cv.put(SQLiteHelper.Quantity,"1");
cv.put(SQLiteHelper.Seller,"Seller1");
cv.put(SQLiteHelper.Tax,"X");
cv.put(SQLiteHelper.Totalprice,"100");
cv.put(SQLiteHelper.Unitprice,"100");
SQLITEDATABASE.insert(SQLiteHelper.TABLE_NAME,null,cv);
ShowSQLiteDBdata();
}
private void ShowSQLiteDBdata() {
SQLITEDATABASE = SQLITEHELPER.getWritableDatabase();
/*>>>>>>>>>> ADDED to display the schema (tables)*/
cursor = SQLITEDATABASE.rawQuery("SELECT * FROM sqlite_master;",null);
DatabaseUtils.dumpCursor(cursor);
cursor = SQLITEDATABASE.rawQuery("SELECT * FROM demoTableb", null);
/*>>>>>>>>>> ADDED to dump the cursor from your code */
DatabaseUtils.dumpCursor(cursor);
CODE_ArrayList.clear();
ITEM_ArrayList.clear();
QUANTITY_ArrayList.clear();
TAX_ArrayList.clear();
UNITPRICE_ArrayList.clear();
TOTALPRICE_ArrayList.clear();
SELLER_ArrayList.clear();
if (cursor.moveToFirst()) {
do {
CODE_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Codes)));
ITEM_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Item)));
QUANTITY_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Quantity)));
TAX_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Tax)));
UNITPRICE_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Unitprice)));
TOTALPRICE_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Totalprice)));
SELLER_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Seller)));
} while (cursor.moveToNext());
}
/*>>>>>>>>>> commented out as the SQLiteAdapter class is not available
ListAdapter = new SQLiteListAdapter(ListViewActivity.this,
CODE_ArrayList,
ITEM_ArrayList,
QUANTITY_ArrayList,
TAX_ArrayList,
UNITPRICE_ArrayList,
TOTALPRICE_ArrayList,
SELLER_ArrayList
);
LISTVIEW.setAdapter(ListAdapter);
*/
cursor.close();
}
}
结果
以上为运行时,App没有崩溃,日志包括:-
I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@b9ccda0
I/System.out: 0 {
I/System.out: type=table
I/System.out: name=android_metadata
I/System.out: tbl_name=android_metadata
I/System.out: rootpage=3
I/System.out: sql=CREATE TABLE android_metadata (locale TEXT)
I/System.out: }
I/System.out: 1 {
I/System.out: type=table
I/System.out: name=demoTableb
I/System.out: tbl_name=demoTableb
I/System.out: rootpage=4
I/System.out: sql=CREATE TABLE demoTableb (code INTEGER PRIMARY KEY, itm VARCHAR, qty INTEGER, tax INTEGER,prc INTEGER,tp INTEGER,slr VARCHAR )
I/System.out: }
I/System.out: <<<<<
模式转储(即 sqlite_master 的内容)
- 有关 sqlite_master
的信息,请参阅 https://www.sqlite.org/schematab.html
这证实了用于创建 table
的 demoTableb table 和 SQL 的存在
- android_metadata 是通过 SQLiteOpenHelper class 生成的 table 并包含语言环境
还包括您的查询根据 :-
生成的 Cursor 的转储
I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@22a7d59
I/System.out: 0 {
I/System.out: code=1
I/System.out: itm=Item1
I/System.out: qty=1
I/System.out: tax=X
I/System.out: prc=100
I/System.out: tp=100
I/System.out: slr=Seller1
I/System.out: }
I/System.out: <<<<<
使用 Database Inspector(现在是 App Inspection)进一步确认一切都符合预期:-
最后在行 cursor.close();
上放置一个断点允许检查来自调试 window 的填充数组,例如:-
- 请注意,数组的大小是 2 而不是 1,因为上面是 运行 第二次和第二行(与第一次相同的数据,但代码列是自动生成,因为它是使用
INTEGER PRIMARY KEY
定义的,没有提供任何值)
因此您原来的问题已经解决,可能是通过卸载并重新安装应用程序,因为 table 可能已更改。
正在进行的问题
如果您遇到持续的问题(ListView 什么都不显示),那应该是 另一个问题,如果是这样,这在很大程度上取决于 SQLiteListAdapter class.
额外
这是一个带有 ListView 的作品 example/demo,更符合我将如何做你正在做的事情。
它没有尝试将游标转换为多个数组然后使用 ListAdapter,而是使用 CursorAdpater (SimpleCursorAdapater)。这些设计用于处理 Cursors 中的数据,因此更简单。
HOWEVER,游标适配器需要一个名为 _id 的列,因此代码列名称已相应更改(它可以保留为是和提取为 _id 的别名)。
访问数据库的代码,例如获取光标的查询已移至助手。
该演示仅插入一行,但包含一个 onItemClickListener,它从数据库中获取被点击的行(您通常不会这样做,但它显示了传递单个值 id 可以在另一个中使用是多么简单activity).
从允许所有相关数据的布局开始(从用户的角度来看)所以 demotableb_layout :-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/item"
android:layout_width="0dp"
android:layout_weight="30"
android:layout_height="match_parent">
</TextView>
<TextView
android:id="@+id/quantity"
android:layout_width="0dp"
android:layout_weight="10"
android:layout_height="match_parent">
</TextView>
<TextView
android:id="@+id/tax"
android:layout_width="0dp"
android:layout_weight="10"
android:layout_height="match_parent">
</TextView>
<TextView
android:id="@+id/unitprice"
android:layout_width="0dp"
android:layout_weight="10"
android:layout_height="match_parent">
</TextView>
<TextView
android:id="@+id/totalprice"
android:layout_width="0dp"
android:layout_weight="10"
android:layout_height="match_parent">
</TextView>
<TextView
android:id="@+id/seller"
android:layout_width="0dp"
android:layout_weight="10"
android:layout_height="match_parent">
</TextView>
</LinearLayout>
- 这显然会更复杂,如果您有这样的布局,那么可以通过对代码进行一些更改(在适配器设置中查看 ID)来使用它
数据库助手建议SQLiteHelper :-
class SuggestedSQLiteHelper extends SQLiteOpenHelper {
static String DATABASE_NAME="DemoDataBaseb";
public static final String TABLE_NAME="demoTableb";
/* column name constant names changed to upper case and more descriptive */
public static final String CODES_COLUMN = BaseColumns._ID; //<<<<<<<<<< renamed for Cursor Adapter
public static final String ITEM_COLUMN ="itm";
public static final String QUANTITY_COLUMN ="qty";
public static final String TAX_COLUMN="tax";
public static final String UNITPRICE_COLUMN ="prc";
public static final String TOTALPRICE_COLUMN ="tp";
public static final String SELLER_COLUMN ="slr";
private SQLiteDatabase db; //<<<<<<<<<< Added
public SuggestedSQLiteHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
db = this.getWritableDatabase(); //<<<<<<<<<< ADDED to instantiate db
}
@Override
public void onCreate(SQLiteDatabase database) {
String CREATE_TABLE="CREATE TABLE IF NOT EXISTS "+TABLE_NAME+" " +
"("+
CODES_COLUMN +" INTEGER PRIMARY KEY, "+
ITEM_COLUMN +" VARCHAR, "+
QUANTITY_COLUMN +" INTEGER, "+
TAX_COLUMN+" INTEGER,"+
UNITPRICE_COLUMN +" INTEGER,"+
TOTALPRICE_COLUMN +" INTEGER,"+
SELLER_COLUMN +" VARCHAR )";
database.execSQL(CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS "+TABLE_NAME);
onCreate(db);
}
public long insertDemoTablebRow(String item, int quantity, int tax, int unitPrice, int totalPrice, String seller) {
ContentValues cv = new ContentValues();
cv.put(ITEM_COLUMN,item);
cv.put(QUANTITY_COLUMN,quantity);
cv.put(TAX_COLUMN,tax);
cv.put(UNITPRICE_COLUMN,unitPrice);
cv.put(TOTALPRICE_COLUMN,totalPrice);
cv.put(SELLER_COLUMN,seller);
return db.insert(TABLE_NAME,null,cv);
}
public boolean isTableEmpty(String tableName) {
return DatabaseUtils.queryNumEntries(db,TABLE_NAME) < 1;
}
public Cursor getAllFromDemoTableb() {
return db.query(TABLE_NAME, null,null,null,null,null,null);
}
public Cursor getDemotablebById(long code) {
return db.query(TABLE_NAME,null,CODES_COLUMN+"=?",new String[]{String.valueOf(code)},null,null,null);
}
}
注意使用了insert和query的便捷方法,这些给你写底层SQL。它们还绑定数据,从而防止 SQL 注入。
请注意评论
最后将它们放在一个 activity 中(相当于您的 ListViewActivity)是 MainActivity :-
public class MainActivity extends AppCompatActivity {
SuggestedSQLiteHelper dbHelper;
Cursor cursor;
SimpleCursorAdapter sca;
ListView listview1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new SuggestedSQLiteHelper(this);
listview1 = this.findViewById(R.id.listview1);
if (dbHelper.isTableEmpty(SuggestedSQLiteHelper.TABLE_NAME)) {
dbHelper.insertDemoTablebRow("Item1",1,5,100,100,"Fred");
}
setOrRefreshListView();
}
private void setOrRefreshListView() {
cursor = dbHelper.getAllFromDemoTableb();
if (sca == null) {
// setup the adapter
// NOTE CURSOR ADAPTERS MUST HAVE _ID column which MUST be type INTEGER and UNIQUE
// see use of BaseColumns._ID in table create
sca = new SimpleCursorAdapter(this,R.layout.demotableb_list,cursor,
// The columns FROM which the data is to be retrieved
new String[]{
SuggestedSQLiteHelper.ITEM_COLUMN,
SuggestedSQLiteHelper.QUANTITY_COLUMN,
SuggestedSQLiteHelper.TAX_COLUMN,
SuggestedSQLiteHelper.UNITPRICE_COLUMN,
SuggestedSQLiteHelper.TOTALPRICE_COLUMN,
SuggestedSQLiteHelper.SELLER_COLUMN
},
// The id of the view's to display the data as per the layout (2nd parm)
new int[]{
R.id.item,
R.id.quantity,
R.id.tax,
R.id.unitprice,
R.id.totalprice,
R.id.seller
},0 // 0 is fine
);
listview1.setAdapter(sca); // Tie the adapter to the ListView
// Can add the Listeners here e.g.
listview1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
// DO SOMETHING HERE NOTING
// long l passed (4th parm) is the _id of the clicked item
// hence l can be passed/used as it uniquely identifies the row
// e.g.
Cursor csr = dbHelper.getDemotablebById(l);
DatabaseUtils.dumpCursor(csr);
csr.close();
}
});
} else {
sca.swapCursor(cursor);
}
}
@Override
protected void onResume() {
super.onResume();
setOrRefreshListView(); //<<<<<<<<<< will refresh the listview in case data has changed
}
@Override
protected void onDestroy() {
cursor.close(); //<<<<<<<<< should always close the cursor when done with it
super.onDestroy();
}
}
结果
运行时的演示:-
点击一个项目(只有上面那个),日志包括:-
I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@1e2064
I/System.out: 0 {
I/System.out: _id=1
I/System.out: itm=Item1
I/System.out: qty=1
I/System.out: tax=5
I/System.out: prc=100
I/System.out: tp=100
I/System.out: slr=Fred
I/System.out: }
I/System.out: <<<<<
原因:java.lang.IllegalStateException:无法从 CursorWindow 读取第 0 行,第 -1 列。在从游标访问数据之前,确保游标已正确初始化。
我在 android 清单中将 android:allowBackup="true" 更改为 "False"。
public class ListViewActivity extends Activity {
SQLiteHelper SQLITEHELPER;
SQLiteDatabase SQLITEDATABASE;
Cursor cursor;
SQLiteListAdapter ListAdapter;
ArrayList<String> CODE_ArrayList = new ArrayList<String>();
ArrayList<String> ITEM_ArrayList = new ArrayList<String>();
ArrayList<String> QUANTITY_ArrayList = new ArrayList<String>();
ArrayList<String> TAX_ArrayList = new ArrayList<String>();
ArrayList<String> UNITPRICE_ArrayList = new ArrayList<String>();
ArrayList<String> TOTALPRICE_ArrayList = new ArrayList<String>();
ArrayList<String> SELLER_ArrayList = new ArrayList<String>();
ListView LISTVIEW;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_view);
LISTVIEW = (ListView)findViewById(R.id.listView1);
SQLITEHELPER = new SQLiteHelper(this);
}
@Override
protected void onResume() {
ShowSQLiteDBdata();
super.onResume();
}
private void ShowSQLiteDBdata() {
SQLITEDATABASE = SQLITEHELPER.getWritableDatabase();
cursor = SQLITEDATABASE.rawQuery("SELECT * FROM demoTableb", null);
CODE_ArrayList.clear();
ITEM_ArrayList.clear();
QUANTITY_ArrayList.clear();
TAX_ArrayList.clear();
UNITPRICE_ArrayList.clear();
TOTALPRICE_ArrayList.clear();
SELLER_ArrayList.clear();
if (cursor.moveToFirst()) {
do {
CODE_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Codes)));
ITEM_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Item)));
QUANTITY_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Quantity)));
TAX_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Tax)));
UNITPRICE_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Unitprice)));
TOTALPRICE_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Totalprice)));
SELLER_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Seller)));
} while (cursor.moveToNext());
}
ListAdapter = new SQLiteListAdapter(ListViewActivity.this,
CODE_ArrayList,
ITEM_ArrayList,
QUANTITY_ArrayList,
TAX_ArrayList,
UNITPRICE_ArrayList,
TOTALPRICE_ArrayList,
SELLER_ArrayList
);
LISTVIEW.setAdapter(ListAdapter);
cursor.close();
}
}
- 错误显示在行
ShowSQLiteDBdata();
和SQLITEDATABASE = SQLITEHELPER.getWritableDatabase();
这是 EditDataActivity
public class EditDataActivity extends Activity {
Button next, previous, update, delete;
EditText item,quantity,tax,unitprice,totalprice,seller;
SQLiteDatabase SQLITEDATABASE, SQLITEDATABASE2;
String GetSQliteQuery, UpdateRecordQuery, DeleteQuery ;
Cursor cursor, cursorCheckDataIsEmptyOrNot ;
TextView purchase;
Boolean CheckEditTextEmpty;
String Item,Quantity,Tax,Unitprice,Totalprice,Seller;
int ItemCode ;
String ConvertCode ;
SQLiteHelper SQLITEHELPER;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_data);
next = (Button)findViewById(R.id.button1);
previous = (Button)findViewById(R.id.button2);
update = (Button)findViewById(R.id.button3);
delete = (Button)findViewById(R.id.button4);
item = (EditText)findViewById(R.id.editText2);
quantity = (EditText)findViewById(R.id.editText3);
tax = (EditText)findViewById(R.id.editText4);
unitprice = (EditText)findViewById(R.id.editText5);
totalprice = (EditText)findViewById(R.id.editText6);
seller = (EditText)findViewById(R.id.editText7);
purchase = (TextView)findViewById(R.id.textview1);
GetSQliteQuery = "SELECT * FROM demoTableb" ;
SQLITEDATABASE = openOrCreateDatabase("DemoDataBaseb", Context.MODE_PRIVATE, null);
cursor = SQLITEDATABASE.rawQuery(GetSQliteQuery, null);
cursor.moveToFirst();
GetSQLiteDatabaseRecords();
next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (!cursor.isLast()){
cursor.moveToNext();
}
GetSQLiteDatabaseRecords();
}
});
previous.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if (!cursor.isFirst()){
cursor.moveToPrevious();
}
GetSQLiteDatabaseRecords();
}
});
update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Item = item.getText().toString();
Quantity = quantity.getText().toString();
Tax = tax.getText().toString();
Unitprice = unitprice.getText().toString();
Totalprice = totalprice.getText().toString();
Seller = seller.getText().toString();
ConvertCode = purchase.getText().toString();
ItemCode = Integer.parseInt(ConvertCode);
UpdateRecordQuery = "UPDATE demoTableb SET Item ='" + Item + "', Quantity ='" + Quantity + "' ,Tax = '"+Tax+"',Unitprice = '"+Unitprice+"',Totalprice = '"+Totalprice+"',Seller ='"+Seller+"' WHERE Code=" + ItemCode + ";";
CheckEditTextIsEmptyOrNot(Item,Quantity,Tax,Unitprice,Totalprice,Seller );
if (CheckEditTextEmpty == false) {
SQLITEDATABASE.execSQL(UpdateRecordQuery);
cursor = SQLITEDATABASE.rawQuery(GetSQliteQuery, null);
cursor.moveToPosition(ItemCode);
Toast.makeText(EditDataActivity.this,"Data Updated Successfully", Toast.LENGTH_LONG).show();
}else {
Toast.makeText(EditDataActivity.this,"Please Fill All the Fields", Toast.LENGTH_LONG).show();
}
}
});
delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
ConvertCode = purchase.getText().toString();
ItemCode = Integer.parseInt(ConvertCode);
DeleteQuery = "DELETE FROM demoTableb WHERE Code=" + ItemCode + ";";
SQLITEDATABASE.execSQL(DeleteQuery);
Toast.makeText(EditDataActivity.this, "Record Deleted Successfully", Toast.LENGTH_LONG).show();
cursor = SQLITEDATABASE.rawQuery(GetSQliteQuery, null);
}
});
}
public void GetSQLiteDatabaseRecords(){
purchase.setText(cursor.getString(0).toString());
item.setText(cursor.getString(1).toString());
quantity.setText(cursor.getString(2).toString());
tax.setText(cursor.getString(3).toString());
unitprice.setText(cursor.getString(4).toString());
totalprice.setText(cursor.getString(5).toString());
seller.setText(cursor.getString(6).toString());
}
public void CheckEditTextIsEmptyOrNot (String Item, String Quantity, String Tax, String Unitprice, String Totalprice,String Seller){
if( TextUtils.isEmpty(Item) || TextUtils.isEmpty(Quantity)|| TextUtils.isEmpty(Tax)|| TextUtils.isEmpty(Unitprice)|| TextUtils.isEmpty(Totalprice) || TextUtils.isEmpty(Seller)){
CheckEditTextEmpty = true ;
}
else {
CheckEditTextEmpty = false ;
}
}
}
这是主要活动
public class SecondActivity extends Activity {
EditText code,item,quantity,tax,unitprice,totalprice,seller ;
Button Submit, EditData, DisplayData;
SQLiteDatabase SQLITEDATABASE;
String Codes,Item,Quantity,Tax,Unitprice,Totalprice,Seller ;
Boolean CheckEditTextEmpty ;
String SQLiteQuery ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.purchase);
code = (EditText)findViewById(R.id.edtcd);
item = (EditText)findViewById(R.id.edtitm);
quantity= (EditText)findViewById(R.id.edtqty);
tax = (EditText) findViewById(R.id.edttax);
unitprice = (EditText) findViewById(R.id.edtprc);
totalprice = (EditText) findViewById(R.id.edttp);
seller = (EditText) findViewById(R.id.edtslr);
Submit = (Button)findViewById(R.id.sbt);
EditData = (Button)findViewById(R.id.edt);
DisplayData = (Button)findViewById(R.id.dply);
Submit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
DBCreate();
SubmitData2SQLiteDB();
}
});
EditData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent i=new Intent(getApplicationContext(),EditDataActivity.class);
startActivity(i);
}
});
DisplayData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent i=new Intent(SecondActivity.this,ListViewActivity.class);
startActivity(i);
}
});
}
public void DBCreate(){
SQLITEDATABASE = openOrCreateDatabase("DemoDataBaseb", Context.MODE_PRIVATE, null);
SQLITEDATABASE.execSQL("CREATE TABLE IF NOT EXISTS demoTableb(Code INTEGER PRIMARY KEY , item INTEGER,quantity INTEGER, tax INTEGER,Unitprice INTEGER,Totalprice INTEGER,Seller VARCHAR);");
}
public void SubmitData2SQLiteDB(){
Codes = code.getText().toString();
Item = item.getText().toString();
Quantity = quantity.getText().toString();
Tax = tax.getText().toString();
Unitprice = unitprice.getText().toString();
Totalprice = totalprice.getText().toString();
Seller = seller.getText().toString();
CheckEditTextIsEmptyOrNot( Codes,Item,Quantity,Tax,Unitprice,Totalprice,Seller);
if(CheckEditTextEmpty == true)
{
SQLiteQuery = "INSERT INTO demoTableb (code,item,quantity,tax,unitprice,totalprice,seller) VALUES('"+Codes+"', '"+Item+"','"+Quantity+"','"+Tax+"','"+Unitprice+"','"+Totalprice+"', '"+Seller+"');";
SQLITEDATABASE.execSQL(SQLiteQuery);
Toast.makeText(SecondActivity.this,"Data Submit Successfully", Toast.LENGTH_LONG).show();
ClearEditTextAfterDoneTask();
}
else {
Toast.makeText(SecondActivity.this,"Please Fill All the Fields", Toast.LENGTH_LONG).show();
}
}
public void CheckEditTextIsEmptyOrNot(String code, String item, String quantity, String tax, String Name, String PhoneNumber, String subject){
if(TextUtils.isEmpty(Codes) || TextUtils.isEmpty(Item) || TextUtils.isEmpty(Quantity) || TextUtils.isEmpty(Tax) || TextUtils.isEmpty(Unitprice) || TextUtils.isEmpty(Totalprice) || TextUtils.isEmpty(Seller)){
CheckEditTextEmpty = false ;
}
else {
CheckEditTextEmpty = true ;
}
}
public void ClearEditTextAfterDoneTask(){
code.getText().clear();
item.getText().clear();
quantity.getText().clear();
tax.getText().clear();
unitprice.getText().clear();
totalprice.getText().clear();
seller.getText().clear();
}
}
public class SQLiteHelper extends SQLiteOpenHelper {
static String DATABASE_NAME="DemoDataBaseb";
public static final String Codes="code";
public static final String TABLE_NAME="demoTableb";
public static final String Item="itm";
public static final String Quantity="qty";
public static final String Tax="tax";
public static final String Unitprice="prc";
public static final String Totalprice="tp";
public static final String Seller="slr";
public SQLiteHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
}
@Override
public void onCreate(SQLiteDatabase database) {
String CREATE_TABLE="CREATE TABLE IF NOT EXISTS "+TABLE_NAME+" ("+Codes+" INTEGER PRIMARY KEY, "+Item+" VARCHAR, "+Quantity+" INTEGER, "+Tax+" INTEGER,"+Unitprice+" INTEGER,"+Totalprice+" INTEGER,"+Seller+" VARCHAR )";
database.execSQL(CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS "+TABLE_NAME);
onCreate(db);
}
}
额外错误
public class MainActivity 扩展 AppCompatActivity {
SuggestedSQLiteHelper dbHelper;
Cursor cursor;
SimpleCursorAdapter sca;
ListView listview1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new SuggestedSQLiteHelper(this);
listview1 = this.findViewById(R.id.listView1);
if (dbHelper.isTableEmpty(SuggestedSQLiteHelper.TABLE_NAME)) {
dbHelper.insertDemoTablebRow("Item1",1,5,100,100,"Fred");
}
setOrRefreshListView();
}
private void setOrRefreshListView() {
cursor = dbHelper.getAllFromDemoTableb();
if (sca == null) {
// setup the adapter
// NOTE CURSOR ADAPTERS MUST HAVE _ID column which MUST be type INTEGER and UNIQUE
// see use of BaseColumns._ID in table create
sca = new SimpleCursorAdapter(this,R.layout.demotableb_layout,cursor,
// The columns FROM which the data is to be retrieved
new String[]{
SuggestedSQLiteHelper.ITEM_COLUMN,
SuggestedSQLiteHelper.QUANTITY_COLUMN,
SuggestedSQLiteHelper.TAX_COLUMN,
SuggestedSQLiteHelper.UNITPRICE_COLUMN,
SuggestedSQLiteHelper.TOTALPRICE_COLUMN,
SuggestedSQLiteHelper.SELLER_COLUMN
},
// The id of the view's to display the data as per the layout (2nd parm)
new int[]{
R.id.item,
R.id.quantity,
R.id.tax,
R.id.unitprice,
R.id.totalprice,
R.id.seller
},0 // 0 is fine
);
listview1.setAdapter(sca); // Tie the adapter to the ListView
// Can add the Listeners here e.g.
listview1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
// DO SOMETHING HERE NOTING
// long l passed (4th parm) is the _id of the clicked item
// hence l can be passed/used as it uniquely identifies the row
// e.g.
Cursor csr = dbHelper.getDemotablebById(l);
DatabaseUtils.dumpCursor(csr);
csr.close();
}
});
} else {
sca.swapCursor(cursor);
}
}
@Override
protected void onResume() {
super.onResume();
setOrRefreshListView(); //<<<<<<<<<< will refresh the listview in case data has changed
}
@Override
protected void onDestroy() {
cursor.close(); //<<<<<<<<< should always close the cursor when done with it
super.onDestroy();
}
}
错误
原因:java.lang.NullPointerException:尝试在空对象引用上调用虚方法 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' 在 com.allmycode.stac.MainActivity.setOrRefreshListView(MainActivity.java:69) 在 com.allmycode.stac.MainActivity.onCreate(MainActivity.java:40)
问题是 getColumnIndex
方法,如果传递了游标中不存在的列名 returns - 1 根据 :-
Returns the zero-based index for the given column name, or -1 if the column doesn't exist. If you expect the column to exist use getColumnIndexOrThrow(java.lang.String) instead, which will make the error more clear. https://developer.android.com/reference/android/database/Cursor#getColumnIndex(java.lang.String)
因为 Cursor 中不存在这样一个预期的列,并且当您使用 SELECT * ....
时,该列不存在于 table demoTableb.
您需要检查 table 和提取的列是否兼容。那就是将缺失的列添加到 table 或从从游标中提取的列中删除缺失的列。
注意 我相信 getColumnIndex
有一个错误,因为它(曾经)区分大小写(过去肯定是)所以问题可能是列名
如果您不确定,那么转储 Cursor 可能会有所帮助。例如你可以使用:-
cursor = SQLITEDATABASE.rawQuery("SELECT * FROM demoTableb", null);
DatabaseUtils.dumpCursor(cursor); //<<<<<<<<<< Will dump the cursor to the log.
这里有一个被丢弃的 Cursor 的例子:-
09-30 08:25:57.238 1933-1933/so52573525.so52573525 D/ADDRESULT: Added row
09-30 08:25:57.238 1933-1933/so52573525.so52573525 I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@456d67
0 {
SEM_ID=1
Date=2018-09-01
Department=Area 1
Topic=Blah
Speaker=Fred
No_of_Students=10
Guests=Tom
Organisation=The org
}
1 {
SEM_ID=2
Date=2018-08-01
Department=Area 2
Topic=Another
Speaker=Mary
No_of_Students=100
Guests=Sue, Tom and Anne
Organisation=Acme
}
<<<<<
从转储中您可以看到 Cursor 中的列是:-
- SEM_ID
- 日期
- 部门
- 话题
- 演讲者
- No_of_Students
- 来宾
- 组织
您还可以看到第 0 行和第 1 行已被提取。
附加 评论:-
i uninstalled and reinstalled it but listview doesn't display.i uploaded th SQLiteHelper above could you pls correct it.
我相信卸载和重新安装可以让您继续前进,也就是说您似乎更改了 table 以添加一列,然后 col -1
被固定为 table 随后被更改,因此该列现在存在。
当然,您的代码的本质是有效的。为了证明它确实有效,我使用您的 SQLiteHelper class 组装了一个测试应用程序,没有任何更改,然后从您的 ListViewActivity 并根据 :-
将其放入 activity (MainActivity)public class MainActivity extends AppCompatActivity {
SQLiteHelper SQLITEHELPER;
SQLiteDatabase SQLITEDATABASE;
Cursor cursor;
//SQLiteListAdapter ListAdapter;
ArrayList<String> CODE_ArrayList = new ArrayList<String>();
ArrayList<String> ITEM_ArrayList = new ArrayList<String>();
ArrayList<String> QUANTITY_ArrayList = new ArrayList<String>();
ArrayList<String> TAX_ArrayList = new ArrayList<String>();
ArrayList<String> UNITPRICE_ArrayList = new ArrayList<String>();
ArrayList<String> TOTALPRICE_ArrayList = new ArrayList<String>();
ArrayList<String> SELLER_ArrayList = new ArrayList<String>();
ListView LISTVIEW;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SQLITEHELPER = new SQLiteHelper(this);
SQLITEDATABASE = SQLITEHELPER.getWritableDatabase();
/* ADDED to insert a row ino the table */
ContentValues cv = new ContentValues();
cv.put(SQLiteHelper.Item,"Item1");
cv.put(SQLiteHelper.Quantity,"1");
cv.put(SQLiteHelper.Seller,"Seller1");
cv.put(SQLiteHelper.Tax,"X");
cv.put(SQLiteHelper.Totalprice,"100");
cv.put(SQLiteHelper.Unitprice,"100");
SQLITEDATABASE.insert(SQLiteHelper.TABLE_NAME,null,cv);
ShowSQLiteDBdata();
}
private void ShowSQLiteDBdata() {
SQLITEDATABASE = SQLITEHELPER.getWritableDatabase();
/*>>>>>>>>>> ADDED to display the schema (tables)*/
cursor = SQLITEDATABASE.rawQuery("SELECT * FROM sqlite_master;",null);
DatabaseUtils.dumpCursor(cursor);
cursor = SQLITEDATABASE.rawQuery("SELECT * FROM demoTableb", null);
/*>>>>>>>>>> ADDED to dump the cursor from your code */
DatabaseUtils.dumpCursor(cursor);
CODE_ArrayList.clear();
ITEM_ArrayList.clear();
QUANTITY_ArrayList.clear();
TAX_ArrayList.clear();
UNITPRICE_ArrayList.clear();
TOTALPRICE_ArrayList.clear();
SELLER_ArrayList.clear();
if (cursor.moveToFirst()) {
do {
CODE_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Codes)));
ITEM_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Item)));
QUANTITY_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Quantity)));
TAX_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Tax)));
UNITPRICE_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Unitprice)));
TOTALPRICE_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Totalprice)));
SELLER_ArrayList.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Seller)));
} while (cursor.moveToNext());
}
/*>>>>>>>>>> commented out as the SQLiteAdapter class is not available
ListAdapter = new SQLiteListAdapter(ListViewActivity.this,
CODE_ArrayList,
ITEM_ArrayList,
QUANTITY_ArrayList,
TAX_ArrayList,
UNITPRICE_ArrayList,
TOTALPRICE_ArrayList,
SELLER_ArrayList
);
LISTVIEW.setAdapter(ListAdapter);
*/
cursor.close();
}
}
结果
以上为运行时,App没有崩溃,日志包括:-
I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@b9ccda0
I/System.out: 0 {
I/System.out: type=table
I/System.out: name=android_metadata
I/System.out: tbl_name=android_metadata
I/System.out: rootpage=3
I/System.out: sql=CREATE TABLE android_metadata (locale TEXT)
I/System.out: }
I/System.out: 1 {
I/System.out: type=table
I/System.out: name=demoTableb
I/System.out: tbl_name=demoTableb
I/System.out: rootpage=4
I/System.out: sql=CREATE TABLE demoTableb (code INTEGER PRIMARY KEY, itm VARCHAR, qty INTEGER, tax INTEGER,prc INTEGER,tp INTEGER,slr VARCHAR )
I/System.out: }
I/System.out: <<<<<
模式转储(即 sqlite_master 的内容)
- 有关 sqlite_master 的信息,请参阅 https://www.sqlite.org/schematab.html
这证实了用于创建 table
的 demoTableb table 和 SQL 的存在- android_metadata 是通过 SQLiteOpenHelper class 生成的 table 并包含语言环境
还包括您的查询根据 :-
生成的 Cursor 的转储I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@22a7d59
I/System.out: 0 {
I/System.out: code=1
I/System.out: itm=Item1
I/System.out: qty=1
I/System.out: tax=X
I/System.out: prc=100
I/System.out: tp=100
I/System.out: slr=Seller1
I/System.out: }
I/System.out: <<<<<
使用 Database Inspector(现在是 App Inspection)进一步确认一切都符合预期:-
最后在行 cursor.close();
上放置一个断点允许检查来自调试 window 的填充数组,例如:-
- 请注意,数组的大小是 2 而不是 1,因为上面是 运行 第二次和第二行(与第一次相同的数据,但代码列是自动生成,因为它是使用
INTEGER PRIMARY KEY
定义的,没有提供任何值)
因此您原来的问题已经解决,可能是通过卸载并重新安装应用程序,因为 table 可能已更改。
正在进行的问题
如果您遇到持续的问题(ListView 什么都不显示),那应该是 另一个问题,如果是这样,这在很大程度上取决于 SQLiteListAdapter class.
额外
这是一个带有 ListView 的作品 example/demo,更符合我将如何做你正在做的事情。
它没有尝试将游标转换为多个数组然后使用 ListAdapter,而是使用 CursorAdpater (SimpleCursorAdapater)。这些设计用于处理 Cursors 中的数据,因此更简单。
HOWEVER,游标适配器需要一个名为 _id 的列,因此代码列名称已相应更改(它可以保留为是和提取为 _id 的别名)。
访问数据库的代码,例如获取光标的查询已移至助手。
该演示仅插入一行,但包含一个 onItemClickListener,它从数据库中获取被点击的行(您通常不会这样做,但它显示了传递单个值 id 可以在另一个中使用是多么简单activity).
从允许所有相关数据的布局开始(从用户的角度来看)所以 demotableb_layout :-
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/item"
android:layout_width="0dp"
android:layout_weight="30"
android:layout_height="match_parent">
</TextView>
<TextView
android:id="@+id/quantity"
android:layout_width="0dp"
android:layout_weight="10"
android:layout_height="match_parent">
</TextView>
<TextView
android:id="@+id/tax"
android:layout_width="0dp"
android:layout_weight="10"
android:layout_height="match_parent">
</TextView>
<TextView
android:id="@+id/unitprice"
android:layout_width="0dp"
android:layout_weight="10"
android:layout_height="match_parent">
</TextView>
<TextView
android:id="@+id/totalprice"
android:layout_width="0dp"
android:layout_weight="10"
android:layout_height="match_parent">
</TextView>
<TextView
android:id="@+id/seller"
android:layout_width="0dp"
android:layout_weight="10"
android:layout_height="match_parent">
</TextView>
</LinearLayout>
- 这显然会更复杂,如果您有这样的布局,那么可以通过对代码进行一些更改(在适配器设置中查看 ID)来使用它
数据库助手建议SQLiteHelper :-
class SuggestedSQLiteHelper extends SQLiteOpenHelper {
static String DATABASE_NAME="DemoDataBaseb";
public static final String TABLE_NAME="demoTableb";
/* column name constant names changed to upper case and more descriptive */
public static final String CODES_COLUMN = BaseColumns._ID; //<<<<<<<<<< renamed for Cursor Adapter
public static final String ITEM_COLUMN ="itm";
public static final String QUANTITY_COLUMN ="qty";
public static final String TAX_COLUMN="tax";
public static final String UNITPRICE_COLUMN ="prc";
public static final String TOTALPRICE_COLUMN ="tp";
public static final String SELLER_COLUMN ="slr";
private SQLiteDatabase db; //<<<<<<<<<< Added
public SuggestedSQLiteHelper(Context context) {
super(context, DATABASE_NAME, null, 1);
db = this.getWritableDatabase(); //<<<<<<<<<< ADDED to instantiate db
}
@Override
public void onCreate(SQLiteDatabase database) {
String CREATE_TABLE="CREATE TABLE IF NOT EXISTS "+TABLE_NAME+" " +
"("+
CODES_COLUMN +" INTEGER PRIMARY KEY, "+
ITEM_COLUMN +" VARCHAR, "+
QUANTITY_COLUMN +" INTEGER, "+
TAX_COLUMN+" INTEGER,"+
UNITPRICE_COLUMN +" INTEGER,"+
TOTALPRICE_COLUMN +" INTEGER,"+
SELLER_COLUMN +" VARCHAR )";
database.execSQL(CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS "+TABLE_NAME);
onCreate(db);
}
public long insertDemoTablebRow(String item, int quantity, int tax, int unitPrice, int totalPrice, String seller) {
ContentValues cv = new ContentValues();
cv.put(ITEM_COLUMN,item);
cv.put(QUANTITY_COLUMN,quantity);
cv.put(TAX_COLUMN,tax);
cv.put(UNITPRICE_COLUMN,unitPrice);
cv.put(TOTALPRICE_COLUMN,totalPrice);
cv.put(SELLER_COLUMN,seller);
return db.insert(TABLE_NAME,null,cv);
}
public boolean isTableEmpty(String tableName) {
return DatabaseUtils.queryNumEntries(db,TABLE_NAME) < 1;
}
public Cursor getAllFromDemoTableb() {
return db.query(TABLE_NAME, null,null,null,null,null,null);
}
public Cursor getDemotablebById(long code) {
return db.query(TABLE_NAME,null,CODES_COLUMN+"=?",new String[]{String.valueOf(code)},null,null,null);
}
}
注意使用了insert和query的便捷方法,这些给你写底层SQL。它们还绑定数据,从而防止 SQL 注入。
请注意评论
最后将它们放在一个 activity 中(相当于您的 ListViewActivity)是 MainActivity :-
public class MainActivity extends AppCompatActivity {
SuggestedSQLiteHelper dbHelper;
Cursor cursor;
SimpleCursorAdapter sca;
ListView listview1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new SuggestedSQLiteHelper(this);
listview1 = this.findViewById(R.id.listview1);
if (dbHelper.isTableEmpty(SuggestedSQLiteHelper.TABLE_NAME)) {
dbHelper.insertDemoTablebRow("Item1",1,5,100,100,"Fred");
}
setOrRefreshListView();
}
private void setOrRefreshListView() {
cursor = dbHelper.getAllFromDemoTableb();
if (sca == null) {
// setup the adapter
// NOTE CURSOR ADAPTERS MUST HAVE _ID column which MUST be type INTEGER and UNIQUE
// see use of BaseColumns._ID in table create
sca = new SimpleCursorAdapter(this,R.layout.demotableb_list,cursor,
// The columns FROM which the data is to be retrieved
new String[]{
SuggestedSQLiteHelper.ITEM_COLUMN,
SuggestedSQLiteHelper.QUANTITY_COLUMN,
SuggestedSQLiteHelper.TAX_COLUMN,
SuggestedSQLiteHelper.UNITPRICE_COLUMN,
SuggestedSQLiteHelper.TOTALPRICE_COLUMN,
SuggestedSQLiteHelper.SELLER_COLUMN
},
// The id of the view's to display the data as per the layout (2nd parm)
new int[]{
R.id.item,
R.id.quantity,
R.id.tax,
R.id.unitprice,
R.id.totalprice,
R.id.seller
},0 // 0 is fine
);
listview1.setAdapter(sca); // Tie the adapter to the ListView
// Can add the Listeners here e.g.
listview1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
// DO SOMETHING HERE NOTING
// long l passed (4th parm) is the _id of the clicked item
// hence l can be passed/used as it uniquely identifies the row
// e.g.
Cursor csr = dbHelper.getDemotablebById(l);
DatabaseUtils.dumpCursor(csr);
csr.close();
}
});
} else {
sca.swapCursor(cursor);
}
}
@Override
protected void onResume() {
super.onResume();
setOrRefreshListView(); //<<<<<<<<<< will refresh the listview in case data has changed
}
@Override
protected void onDestroy() {
cursor.close(); //<<<<<<<<< should always close the cursor when done with it
super.onDestroy();
}
}
结果
运行时的演示:-
点击一个项目(只有上面那个),日志包括:-
I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@1e2064
I/System.out: 0 {
I/System.out: _id=1
I/System.out: itm=Item1
I/System.out: qty=1
I/System.out: tax=5
I/System.out: prc=100
I/System.out: tp=100
I/System.out: slr=Fred
I/System.out: }
I/System.out: <<<<<