【问题标题】:Populating listview from a different activity with items from a SQLite database使用 SQLite 数据库中的项目填充来自不同活动的列表视图
【发布时间】:2011-11-30 18:15:55
【问题描述】:

我有一个扩展 ListActivity 的类,我拥有管理数据库项目的所有方法:insertItems()、getItems()、showItems() 等。当我使用数据库中的项目填充此列表视图时,一切都很好。我想要做的是以同样的方式从另一个活动中填充另一个 ListView,但是当我试图将光标传递给该活动时,我得到 NullPointer 异常。我尽量说最有代表性的。

public class FOO extends ListActivity{
//...
public static DBAdapter items;
@override
public void onCreate(){
   //...
   items = new DBAdapter(this);
   //...
}
public static Cursor getAllItems() {
    // TODO Auto-generated method stub
    db = items.getReadableDatabase();
    return db.query(DBConstants.TABLE_NAME, FROM, null, null, null, null, null);
   }

那么,在我的第二个活动中:

public class BAR extends ListActivity{
//.....
public FOO foo = new FOO();
Cursor cursor;
 //...
public static DBAdapter items;
@override
public void onCreate(){
   //...
   items = new DBAdapter(this);
   foo.insertItems(//arguments);
   this.cursor = foo.getAllItems();
   this.startManagingCursor(this.cursor);
   ListAdapter adapter = new SimpleCursorAdapter(this, R.layout.item_list, cursor,     FROM, TO);
    setListAdapter(adapter);
}

我首先得到的是这个错误,其中 MainActivity = BAR

 E/AndroidRuntime(22923): java.lang.RuntimeException: Unable to start activity ComponentInfo{your.pack.databasae/your.pack.databasae.MainActivity}: java.lang.NullPointerException

【问题讨论】:

  • 能否包含项目的实例化?它看起来好像是一个 SQLiteOpenHelper,如果没有 Context 的实例(例如,一个 Activity)就无法实例化它,但是你从一个没有这样的实例的静态方法返回它。我的猜测是它的项目是空的。
  • 是的,你没看错,DBAdapter 是扩展 SQLiteOpenHelper 的类。我在两个类中都以相同的方式实例化了 items,我不知道是否可以....
  • 好的,我现在知道了。 Foo 的实例起什么作用?在没有看到 Foo.insertItems 的情况下,我猜测它在一个单独的静态 DBAdapter 实例上运行,该实例预计将在 Foo 的 onCreate 方法中实例化。在每个活动的生命周期内实例化和使用 DBAdapter 可能会更好,而且绝对不是静态的。而且您根本不应该实例化其他活动。我希望这会有所帮助。如果不能随意包含整个堆栈跟踪。

标签: android sqlite android-listview android-activity


【解决方案1】:

public FOO foo = new FOO();

您永远不应该创建这样的活动,这取决于框架来根据需要构建活动。也就是说,如果您需要这样做,请确保在 FOO 的构造函数中创建 itemsdb(典型代码会在 onCreate() 中创建它,这将导致此处出现 NPE)。 BAR 中没有任何东西调用 FOO 的 onCreate,所以 items 和大概 db 都是空的。

或者,尝试重构您的代码,以使数据库管理代码可在可从两个 ListActivity 类访问的单独类中使用。

【讨论】:

  • 是的,你是对的。 itemsdb 是在 FOO 中的某个位置创建的,在 onCreate() 中,而不是在构造函数中,但我还在 BAR 中实例化了 items。我已经声明 new FOO() 只是为了能够调用 getAllItems
  • 不幸的是 getAllItems() 引用了一个空类成员。我真的建议从活动中取出数据库代码以促进重用。请注意,如果您从 BAR 调用 FOO 的 onCreate(),您会收到其他错误...
  • 我同意你永远不应该创建这样的活动,我不同意“说”之后的警告。您永远不应该直接从另一个活动实例化一个活动,期间。当您绕过正常的活动生命周期管理时,它从来没有必要并且会导致任何数量的奇怪问题。如果有两个 Activity 需要共享的非 UI 行为,则应按照 Chris 和其他人的建议将其移到单独的类中。
  • 好的,伙计们,让我们看看我是否明白了,你建议我创建一个新类BAZ,这不是一个活动,将所有与数据库一起使用的方法放在哪里,包括@987654334 @.Than,这样做是否安全:public BAZ baz = new BAZ(),然后在我的 ListActivity 中使用 baz.getAllItems()?让我头疼的是,在哪里以及如何实例化 items,如果我只在 BAZ 中执行就足够了?请提供更多建议:D
  • 好的,我已经把所有这些都付诸实践了,成功了!我创建了一个管理数据库访问的新类,它有一个构造函数,我在其中使用新的上下文启动 items,而不是在我的 ListActivity 中使用new BAZ(this) 调用它。希望是个好习惯。谢谢大家的提示!
【解决方案2】:

我建议你再创建两个类:

  • 一个数据库适配器类,您可以在其中处理数据库访问
  • AsyncTask 的子类,用于处理向/从数据库中保存/加载数据。在此任务中,您还可以使用数据填充列表视图。

也许Fragments 对您来说也是个不错的解决方案

【讨论】:

  • 这个解决方案可能很好,但由于我是新手,想必会被锁定。但我会分析片段,因为它似乎非常有用,还有 AsyncTask,我会尝试了解它是如何工作的。 :D 谢谢
猜你喜欢
  • 2017-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-19
  • 1970-01-01
相关资源
最近更新 更多