我觉得我错过了简单而愚蠢的事情。我有一个列表视图,顶部有几个按钮。列表视图最初填充了数据。单击按钮时,列表视图应根据Where语句中已更改的变量填充其自身。实际上我可能只是开始一个新的List活动,但我觉得有更好的方法。
我一直在阅读CursorAdapter.changeAdapter()
和notifydatasetchanged()
我还没有实现这个,因为我有一个更基本的问题。
我可以成功查询数据库并在列表中显示静态结果。当我尝试将进程分解为步骤时,我遇到了错误:fillWindow
中的语句无效。我理解的最好的原因是不正确关闭游标数据库和数据库帮助程序,因此人们使用内容提供程序。
现在我只想让它发挥作用。
public class DListView extends ListActivity implements OnClickListener{
public static final String NAME = "Name";
public static final String DESCRIPT = "Description";
public static final String DATABASE_TABLE = "Table";
public static final String DAY = "Day_id";
/** Called when the activity is first created. */
private Cursor c = null;
private String[] colsfrom = {"_id", NAME, DESCRIPT, DAY};
private int[] to = new int[] {R.id.text01, R.id.text02, R.id.text03, R.id.text04};
public int b = 0;
public int d = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.drinklistview);
View left = findViewById(R.id.left_button);
left.setOnClickListener(this);
View right = findViewById(R.id.right_button);
right.setOnClickListener(this);
Intent thisIntent = getIntent();
b = thisIntent.getIntExtra("_b", 0);
//0 is the default argument is nothing is passed.
d = thisIntent.getIntExtra("_d", 0); //same idea as above.
c = fillList();
/*this creates a new cursor adapter
@param Context is the list context that you will be filling.
@param int layout is the layout that you will use for the rows
@param Cursor is the cursor that was returned from the query
@param from is the column names
@param to is the layout ids that the fields will be put in.
@param from is the column names to map from
@param to is the layout ids that the column fields will be put in.
*/
SimpleCursorAdapter myAdapter = new SimpleCursorAdapter(this, R.layout.row, c, colsfrom, to);
setListAdapter(myAdapter);
}
private Cursor fillList() {
DBHelper DbHelper = new DBHelper(this);
Cursor cursor;
String wHERE = "_id = " + b + " AND Day_id = " + d ;
try {
myDbHelper.openDataBase();
}
catch(SQLException sqle){
throw sqle;
}
cursor = myDbHelper.getDrinks(DATABASE_TABLE, colsfrom, wHERE, null, null,null, null);
myDbHelper.close();
return cursor;
}
当我将fillList()的内容放在onCreate()中时,它显示数据就好了。当我把它拉出来时,它给了我错误。为什么会这样?如果有人有更好的方法来解决这个问题,我很乐意阅读它。或者我们可以玩一个名为“我做错了什么愚蠢的事情现在? 三江源。
编辑:来自DBHelper
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();
}
我认为我的问题行是super.close()我相信这行关闭数据库及其附属的任何东西,这意味着我在关闭后尝试使用的游标。我可能错了。请解释一下你是否可以。
答案 0 :(得分:0)
您的问题就在这里,在fillList()
:
myDbHelper.close(); // <--- here
return cursor;
你创建一个游标对象但是在你使用它之前关闭你的数据库连接(数据库的这个组件),如果你愿意,它会使它无用或为null。通常关闭光标然后数据库。但这并没有抛出错误。那个错误特别是是因为你将这个光标连接到一个cursorAdapter,试图用什么来填充你的listView。移动它,它应该消失。
那么你搬到哪里呢?如果你有一个连接到listView的游标,它需要在整个时间打开,否则你会收到另一个错误,说“尝试重新打开已经关闭的对象”。我建议放入onDestroy()
然后再查看listView。
答案 1 :(得分:0)
YaY解决了。芒果是完全正确的。谢谢你的建议,关闭光盘在破坏。我不确定super.close()行是否关闭了我的光标。但我会调查一下。我也打算将数据库查询放在异步任务中,以解决问题和傻笑。
我只是移动了创建新SimpleCursorAdapter的两行,并将列表视图设置为fillList方法。
我还实现了我的按钮,最后添加了fillList。 这是解决问题的代码。简单的错误。
private void fillList() {
DBHelper DbHelper = new DBHelper(this);
Cursor cursor;
String wHERE = "_id = " + b + " AND Day_id = " + d ;
try {
myDbHelper.openDataBase();
}
catch(SQLException sqle){
throw sqle;
}
cursor = myDbHelper.getDrinks(DATABASE_TABLE, colsfrom, wHERE, null, null,null, null);
SimpleCursorAdapter myAdapter = new SimpleCursorAdapter(this, R.layout.row, cursor, colsfrom, to);
setListAdapter(myAdapter);
myDbHelper.close();
}
这是我再次调用fillList来更新我的列表视图。
public void onClick(View v) {
switch(v.getId()) {
//Mess with d based on button click
}
fillList();
}
现在,每次更改内容时,应用程序都必须创建一个新的简单游标适配器。 如果有人在没有创建新CursorAdapter的情况下有任何实现这一点的想法,那么每次都会有很大帮助,但我的初始问题已经解决了。谢谢您的帮助。事实上,你想看到我的堆栈跟踪告诉我,我在最初提出的代码中没有做任何错误,我忘了我让我的dbHelper关闭所有连接。谢谢芒果。我昨晚解决了这个问题,但无法发布。谢谢你的解释好先生。如果您对不断创建新的cursoradapter有任何见解,我会很高兴看到它。也许我需要以某种方式修复super.close()命令。