在非Activity类中访问数据库

5
我有一个类 (SomeClass.class),我想在其中添加一些静态方法,例如 getAllDatabaseItems、getTableItems、insertNewRecord 等等。
如果我这样做:
SQLiteDatabase db = openOrCreateDatabase(DATABASE_NAME, MODE_PRIVATE, null);
  • 我需要扩展Activity(但仍然不能在静态方法中使用它),或者在每个方法中传递一个“db”变量(从“调用活动”中),这相当冗长。

那么我可以从某个类中调用SomeClass.getAllDatabaseItems()吗?

@MobileDev123 那我是否仍然需要扩展Activity(因为有openOrCreateDatabase方法)? 如果我有这个类(实际上不是活动,我不会这样使用它)

public class Partner extends Activity {
@SuppressWarnings("static-access")
public Partner(Context mContext) {
    myContext = mContext;
    db = openOrCreateDatabase(DATABASE_NAME, myContext.MODE_PRIVATE, null);

    db.execSQL("CREATE TABLE IF NOT EXISTS " + PARTNER_TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, " + NAME + " VARCHAR);");
    db.execSQL("CREATE TABLE IF NOT EXISTS " + ADDRESS_TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, " + PARTNER_ID + " INT, " + ADDRESS + " VARCHAR, " + CITY + " VARCHAR);");
}

然后在我的一些活动中像这样调用它

    Partner newPartner = new Partner(this);
    partnersItems = newPartner.getAllItems();

我在第4行(Partner.class)遇到了一个空指针异常错误 - 为什么?如果我使用静态引用

MODE_PRIVATE => (Context.MODE_PRIVATE)

再次出现问题。

@Falmarri 如果我在静态方法中传入“this”参数(来自某个调用类),并将其作为Context参数接收,仍然无法成功创建/打开我的数据库(请参见前面的行)。


据我所知,@svbee,您至少有一个服务或活动...它可以直接调用您的类或在调用层次结构中调用(即activity-->A-->B--->您的类)...在这种情况下,您必须将context传递给所有类。如果您的类具有任何视图控件,可以使用View.getContext()获取它们。 - Prasham
@svbee 我的理解是你需要在你的类中使用一个上下文对象,当我遇到这种问题时,我通常是这样做的。也许有更好的答案,但在那之前你可以使用它...对我来说它很有效。 - Prasham
修改了我的回答,请看一下... - Prasham
4个回答

4

必须有一个调用您类的活动或服务,您可以在方便的时间传递this(我更喜欢在构造函数中传递它)。

在接收端使用上下文实例。

例如:从MyActivity类中,您可以调用createDatabase(this)new DataServices(this),但在DataServices类中,参数类型必须是context而不是MyActivity

现在您拥有上下文参数,您可以按您想要的方式使用它,包括调用openOrCreateDatabase()

编辑:添加代码

来自Main.java

写入

DataBase database = new DataBase(this); //This will pass an instance of main. Which is eventually the subclass of Context.java

在DataBase类中,不需要扩展活动。在构造函数定义中:public DataBase(Context context); 如果您正在使用Eclipse并依赖于某些自动化工具,则可以看到像Main main这样的东西。但是使用这些行,因此您可以通过传递this从任何活动或服务中调用它。定义Context类的字段,并将其引用到上下文参数。例如:this.localContext=context; 通过使用localContext变量,您可以调用openOrCreateDataBase列。补充:如果您附加了任何控件(视图的子类),则可以通过调用new DataBase(view.getContext());来实例化DataBase。希望这会对您有所帮助...如果需要更多帮助,请随时在下面发表评论。

你能提供一些示例代码吗?我还是没弄对(显然):/ 仍然出现空值错误。 - svenkapudija
为什么不呢?但在此之前,我想需要您的帮助。1. 您的应用程序启动的类名是什么?这是一个活动还是服务?2. 我需要您的类结构...从您的活动起始点到该类。别忘了提到任何视图控件是否调用了您想要创建数据库的类。 - Prasham
  1. 这是一个常规活动(Main.java - 类Main扩展Activity)
  2. 为了保持简单 - 我只有另一个公共类(DatabaseOptions.java - 类DatabaseOptions扩展Activity),我想在其中拥有与我的数据库相关的所有选项,以便在需要时可以从任何其他Activity类(而不仅仅是Main.java)中调用它。因此只有两个类,一个是常规活动Main.java(显示UI等),另一个是DatabaseOptions.java,应该关心我所有的数据库操作。
- svenkapudija
执行this.localContext=context;不是一种不好的做法吗?有人称之为持有上下文或上下文泄漏吗?每次需要时传递它是否更好,从而使类无状态并且不保留对上下文的引用? - Nom1fan

1

你不需要上下文。使用SQLiteDatabase的静态方法:

public static SQLiteDatabase openOrCreateDatabase (String path, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler)
public static SQLiteDatabase openOrCreateDatabase (String path, SQLiteDatabase.CursorFactory factory)
public static SQLiteDatabase openOrCreateDatabase (File file, SQLiteDatabase.CursorFactory factory)

或者:


public static SQLiteDatabase openDatabase(String path, SQLiteDatabase.CursorFactory factory, int flags, DatabaseErrorHandler errorHandler)
public static SQLiteDatabase openDatabase(String path, SQLiteDatabase.CursorFactory factory, int flags)


0

我不确定直接做到这一点是否可能。我自己也曾经为此苦苦挣扎,但每个应用程序都使用不同的数据库句柄,因此Android需要知道如何在从那个如此方便的地方获取句柄时抓取它(上下文):

SQLiteDatabase db = (SQLiteDatabase)(new SQLOpenHelperDerivedClass(this)).getReadableDatabase();

也许你可以想出如何绕过 SQLOpenHelper 并使用硬编码路径到数据库。不过,SQLOpenHelper 可能为你提供了很多有用的功能,如果放弃它们,可能会有所损失。我想这对于实现跨设备应该是至关重要的。

也许你可以想出如何绕过 SQLOpenHelper 并使用硬编码路径来访问数据库。不行。 - Falmarri

0
你需要一个上下文环境。如果你想在静态方法中实现此功能,它必须接受上下文环境作为参数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接