我(已经有一段时间)致力于一个Android项目,它将作为一个非常基本的课程安排应用程序。到目前为止,我有以下工作:向数据库添加课程,从数据库中删除课程,在列表中显示具有位置和主题的课程,打开“作业”菜单以创建课程作业。
问题在于,当我尝试单击作业创建菜单上的保存按钮时,它只是不会将作业添加到列表中。
作业列表是“courses”数据库中的第二个表(标记为lunchlist.db)。下面是三个负责处理作业的课程。
作业清单:
public class AssList extends ListActivity {
public final static String ID_EXTRA = "apt.tutorial._ID";
Cursor model = null;
AssAdapter adapter = null;
AssHelper helper = null;
SharedPreferences prefs = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ass);
helper = new AssHelper(this);
}
@Override
public void onDestroy() {
super.onDestroy();
helper.close();
}
@Override
public void onListItemClick(ListView list, View view, int position, long id) {
Intent i = new Intent(AssList.this, AssForm.class);
i.putExtra(ID_EXTRA, String.valueOf(id));
startActivity(i);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
new MenuInflater(this).inflate(R.menu.ass_option, menu);
return (super.onCreateOptionsMenu(menu));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.add_ass) {
startActivity(new Intent(AssList.this, AssForm.class));
return (true);
}
return (super.onOptionsItemSelected(item));
}
public void initList() {
if (model != null) {
stopManagingCursor(model);
model.close();
}
model = helper.getAll(prefs.getString("sort_order", "name"));
startManagingCursor(model);
adapter = new AssAdapter(model);
setListAdapter(adapter);
}
private SharedPreferences.OnSharedPreferenceChangeListener prefListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
public void onSharedPreferenceChanged(SharedPreferences sharedPrefs,
String key) {
if (key.equals("sort_order")) {
initList();
}
}
};
class AssAdapter extends CursorAdapter {
AssAdapter(Cursor c) {
super(AssList.this, c);
}
@Override
public void bindView(View row, Context ctxt, Cursor c) {
AssHolder holder = (AssHolder) row.getTag();
holder.populateFrom(c, helper);
}
@Override
public View newView(Context ctxt, Cursor c, ViewGroup parent) {
LayoutInflater inflater = getLayoutInflater();
View row = inflater.inflate(R.layout.row, parent, false);
AssHolder holder = new AssHolder(row);
row.setTag(holder);
return (row);
}
}
static class AssHolder {
private TextView name = null;
private TextView address = null;
private ImageView icon = null;
AssHolder(View row) {
name = (TextView) row.findViewById(R.id.title);
address = (TextView) row.findViewById(R.id.address);
icon = (ImageView) row.findViewById(R.id.icon);
}
void populateFrom(Cursor c, AssHelper helper) {
name.setText(helper.getName(c));
address.setText(helper.getUrgency(c));
if (helper.getUrgency(c).equals("normal")) {
icon.setImageResource(R.drawable.eg);
} else if (helper.getUrgency(c).equals("pending")) {
icon.setImageResource(R.drawable.ey);
} else {
icon.setImageResource(R.drawable.er);
}
}
}
}
作业表格:
public class AssForm extends Activity {
EditText name = null;
RadioGroup types = null;
AssHelper helper = null;
String AssId = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ass_edit);
helper = new AssHelper(this);
name = (EditText) findViewById(R.id.assname);
types = (RadioGroup) findViewById(R.id.urge);
Button save = (Button) findViewById(R.id.save_ass);
Button del = (Button) findViewById(R.id.del_ass);
save.setOnClickListener(onSave);
del.setOnClickListener(onDel);
AssId = getIntent().getStringExtra(AssList.ID_EXTRA);
if (AssId != null) {
load();
}
}
@Override
public void onDestroy() {
super.onDestroy();
helper.close();
}
private void load() {
Cursor c = helper.getById(AssId);
c.moveToFirst();
name.setText(helper.getName(c));
if (helper.getUrgency(c).equals("normal")) {
types.check(R.id.normal);
} else if (helper.getUrgency(c).equals("pending")) {
types.check(R.id.pending);
} else {
types.check(R.id.due);
}
c.close();
}
private View.OnClickListener onSave = new View.OnClickListener() {
public void onClick(View v) {
String type = null;
switch (types.getCheckedRadioButtonId()) {
case R.id.normal:
type = "normal";
break;
case R.id.pending:
type = "pending";
break;
case R.id.due:
type = "due";
break;
}
if (AssId == null) {
helper.insert(name.getText().toString(), type);
} else {
helper.update(AssId, name.getText().toString(), type);
}
finish();
}
};
private View.OnClickListener onDel = new View.OnClickListener() {
public void onClick(View v) {
helper.deleteValue(name.getText().toString());
finish();
}
};
}
作业助手:
class AssHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "lunchlist.db";
private static final int SCHEMA_VERSION = 1;
public AssHelper(Context context) {
super(context, DATABASE_NAME, null, SCHEMA_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE assignments (_id INTEGER PRIMARY KEY AUTOINCREMENT, assname TEXT, urge TEXT);");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// no-op, since will not be called until 2nd schema
// version exists
}
public Cursor getAll(String orderBy) {
return (getReadableDatabase().rawQuery(
"SELECT _id, assname, urge FROM assignments ORDER BY "
+ orderBy, null));
}
public Cursor getById(String id) {
String[] args = { id };
return (getReadableDatabase().rawQuery(
"SELECT _id, assname, urge FROM assignments WHERE _ID=?",
args));
}
public void insert(String name, String type) {
ContentValues cv = new ContentValues();
cv.put("assname", name);
cv.put("urge", type);
getWritableDatabase().insert("assignments", "assname", cv);
}
public void deleteValue(String value) {
SQLiteDatabase db = getWritableDatabase();
String whereClause = "assname" + "=?";
String[] whereArgs = new String[] { String.valueOf(value) };
db.delete("assignments", whereClause, whereArgs);
db.close();
}
public void update(String id, String name, String type) {
ContentValues cv = new ContentValues();
String[] args = { id };
cv.put("assname", name);
cv.put("urge", type);
getWritableDatabase().update("assignments", cv, "_ID=?", args);
}
public String getName(Cursor c) {
return (c.getString(1));
}
public String getUrgency(Cursor c) {
return (c.getString(2));
}
}
我知道要阅读很多内容,但是我真的被困在我的项目的最后一部分。这三个类(用于所有意图和目的)几乎与添加课程的三个类相同。唯一的区别是变量名称已更改,并且类引用已切换为与赋值类匹配。任何帮助或批评都非常受欢迎。提前感谢您花时间阅读我的问题。
答案 0 :(得分:1)
将编辑或条目保存到数据库后,需要重新加载光标并在列表视图上调用notifydatasetchanged()
以告知其刷新。由于提交表单和列表视图在不同的活动中,并且一个必须在另一个之上,我认为最直接的方法是在列表活动的OnResume()
方法上执行这些操作,也许煽动有条件的意图,以避免无用的刷新。更直接的是简单地确保listactivity在视图外总是“完成”,这样每次看到它都是一个新实例,从而重置光标。
检查上述内容是否正确的一个好方法是完全关闭应用,看看您的应用重新启动时是否有编辑或条目。
编辑:嗯,你的问题让我感到好奇,最终我屈服了,只是自己运行了完整的代码并自己测试了这个解决方案。我不敢相信我们都错过了它,但问题并不在于事情没有添加到你的列表视图中,而是你的列表视图根本没有显示。问题是你的listview从未连接到游标适配器。这就是你所需要的:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ass);
helper = new AssHelper(this);
loadListview();
}
private void loadListview() {
Cursor c = helper.getAll("urge");
mAdapter = new AssAdapter(c);
setListAdapter(mAdapter);
}
我做了一个单独的3行代码的单独方法,因为你的listview实际上确实需要在返回活动时刷新。你可能不想这样做,但因为我很懒,我选择以下列方式做到这一点:
@Override
protected void onResume() {
super.onResume();
loadListview();
}
我个人的问题是光标的第一个实例永远不会有机会被关闭,这是一个有点不优雅的imo。顺便说一下,这与问题无关,但是你的代码使用了不推荐使用的方法(例如不推荐的游标构造函数,startManagingCursor
...),你可能想也可能不想考虑修改这些部分。还记得在完成后关闭游标和数据库。
答案 1 :(得分:1)
作为替代方法,您可以将数据库包装在ContentProvider中,然后使用CursorLoader来管理Cursor。 CursorLoader在后台线程上运行(yay!)并在其基础数据发生变化时自动重新加载Cursor。
ContentProvider提供了一些开销,但它隐藏了许多混乱的数据库内容,否则你必须自己处理。虽然文档说您没有 使用内容提供商来使用数据库,但内容提供商有时会更好。它更好,因为它可以节省你的时间。我怀疑大多数应用程序的性能总体上不受使用内容提供商的影响。