gpt4 book ai didi

java - 带有临时类实例的垃圾收集

转载 作者:行者123 更新时间:2023-11-29 21:44:34 24 4
gpt4 key购买 nike

我是 android 开发的新手并且来自 c# 背景,我的整个策略完全有可能是错误的,但是在调试时我不断收到 Eclipse 警告我没有正确关闭数据库连接导致内存泄漏.

我有一个扩展 SQLiteOpenHelper 的基础数据库类:

public class MySQLiteOpenHelper extends SQLiteOpenHelper {

public MySQLiteOpenHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
}

public MySQLiteOpenHelper(Context context) {
this(context, "myDb", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE MyTable (A INT)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}

public Cursor executeSelect(String sql, String[] parameters) {
return getReadableDatabase().rawQuery(sql, parameters);
}

}

通用实体:


public class MyClass {
private int a;

public void setA(int value) {
this.a = value;
}

public int getA() {
return this.a;
}
}

本质上是 MyClass 的服务(尽管实际上它扩展了一个通用抽象类以实现可重用性目的)


public class MyClassService {

private MySQLiteOpenHelper helper;
private Context context;

public MyClassService(Context context) {
this.context = context;
}

private MySQLiteOpenHelper getHelper() {
if (helper == null) {
helper = new MySQLiteOpenHelper(this.context);
}
return helper;
}

public void dispose() {
if (helper != null) {
helper.close();
helper = null;
}
}
public ArrayList<MyClass> getAll()
{
ArrayList<MyClass> list = new ArrayList<MyClass>();
Cursor cursor = getHelper().executeSelect("SELECT A FROM MyTable", new String[0]);

while (cursor.moveToNext()) {
MyClass item = new MyClass()
item.setA(cursor.getInt(0));
list.add(item);
}
cursor.close();
return list;
}
}

所以,我的问题是,当我从 Activity 使用这样一行代码时:

ArrayList<MyClass> list = new MyClassService(this).getAll();

MyClassService 的实例是否立即被处理掉,或者这可能是我的内存泄漏的根源。

我是否会更好地调用完整代码以确保使用 dispose 方法关闭数据库?

MyClassService svc = new MyClassService(this);
ArrayList<MyClass> list = svc.getAll();
svc.dispose();

最佳答案

垃圾收集器 将能够收集您的类,以及 Helper类,因为它们不再是对象链的一部分(不是技术术语 - 只是我编造的)。但是,您仍然需要显式关闭数据库(如果不这样做,这肯定是内存泄漏的罪魁祸首)。就目前而言,您可以在对象的 finalize() 中执行此操作方法,在垃圾收集期间调用:

@Override
public void finalize() {
dispose();
}

不过,我通常更喜欢做一些不同的事情。像这样的 Data Stores 通常最好写成 Singletons,因为它们可能被多个类访问,如果创建不同的实例,它们仍然会打开一个新的访问点来读取写入,并且可能导致许多问题。你有一种单例风格的设置,因为有一个 helper变量在你的代码中,但你可能只想让你的 Helper给单例上课。您可以通过删除构造函数并添加以下内容来完成此操作:

private static MySQLiteOpenHelper self;

private MySQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) {
super(context, name, factory, version);
}

private MySQLiteOpenHelper(Context context) {
this(context, "myDb", null, 1);
}

public static MySQLiteOpenHelper sharedHelper(Context context) {
if (self == null)
self = new MySQLiteOpenHelper(context);
return self;
}

然后,不再跟踪 MyClassService 中的辅助对象使用 getHelper() ,您可以使用以下方法获得帮助程序:

MySQLiteOpenHelper.sharedHelper(context);

这样做的好处是您只需在整个应用程序中跟踪一个助手,并在助手的 finalize() 中方法,您现在可以关闭数据库。这将在应用程序进程被终止时调用,并防止任何内存泄漏:

public void finalize()
{
close();
}

关于java - 带有临时类实例的垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16241486/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com