Android 泄漏发现SQL数据库从未关闭

Android 泄漏发现SQL数据库从未关闭,android,database,sqlite,memory-leaks,Android,Database,Sqlite,Memory Leaks,我正在制作一个烹饪应用程序。我创建了三个SQL数据库,并用tabview填充了一个列表。 这是数据库 import android.content.ContentValues; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class Cook_tab_mains_data

我正在制作一个烹饪应用程序。我创建了三个SQL数据库,并用tabview填充了一个列表。 这是数据库

import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class Cook_tab_mains_data extends SQLiteOpenHelper {

public static final String DATABASE_NAME = "mains";

public Cook_tab_mains_data(Context context) {
    super(context, DATABASE_NAME, null, 2);
}

@Override
public void onCreate(SQLiteDatabase db) {

    String sql = "CREATE TABLE IF NOT EXISTS mains (" +
                    "_id INTEGER PRIMARY KEY AUTOINCREMENT, " + 
                    "name TEXT, " +
                    "disc TEXT, " +
                    "photo TEXT, " +
                    "prep TEXT, " +
                    "thumb TEXT, " +
                    "ingre TEXT, " +
                    "howto TEXT, " +
                    "info TEXT, " +
                    "mainId INTEGER)";
    db.execSQL(sql);

    ContentValues values = new ContentValues();


    values.put("name", "Name 3");
    values.put("disc", "here is the description");
    values.put("photo", "stub.png");
    values.put("ingre", "the ingredients of the mains");
    values.put("howto", "how to make this thing");
    values.put("info", "basically its this much calorie and such and such");
    db.insert("mains", "name", values);

    values.put("name", "Name 4");
    values.put("disc", "here is the description");
    values.put("photo", "stub.png");
    values.put("thumb", "ic_launcher.png");
    values.put("ingre", "the ingredients of the mains");
    values.put("howto", "how to make this thing");
    values.put("info", "basically its this much calorie and such and such");
    db.insert("mains", "name", values);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS mains");
    onCreate(db);
}}
正如您所看到的,我的数据库是静态的。 现在,我有一个列出项目的列表活动和另一个详细列出项目的列表活动:

import java.io.IOException;
import java.io.InputStream;

import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

public class Cook_tab_mains extends ListActivity {

protected EditText searchText;
protected SQLiteDatabase db;
protected Cursor cursor;
protected ListAdapter adapter;
 class CustomSimpleCursor extends SimpleCursorAdapter {

        public CustomSimpleCursor(Context context, int layout, Cursor c,
                        String[] from, int[] to) {
                super(context, layout, c, from, to);
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
                super.bindView(view, context, cursor);
                ImageView thumb = (ImageView) view.findViewById(R.id.thumb);
                try {
                        InputStream bitmap = getAssets()
                                        .open(cursor.getString(cursor
                                                        .getColumnIndexOrThrow("thumb")));
                        Bitmap bit = BitmapFactory.decodeStream(bitmap);
                        thumb.setImageBitmap(bit);
                } catch (IOException e1) {
                        e1.printStackTrace();
                }

        }
}


/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.cook_tab_general);
    db = (new Cook_tab_mains_data(this)).getWritableDatabase();
    searchText = (EditText) findViewById (R.id.searchText);

EditText searchTo = (EditText)findViewById(R.id.searchText);
searchTo.addTextChangedListener(new TextWatcher() {

    @Override
    public void afterTextChanged(Editable s) {
    }
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        // autoclick
    } 
});

    // || Query  SQLite
    cursor = db.rawQuery("SELECT _id, name, disc, thumb, prep FROM mains WHERE name LIKE ?", 
                    new String[]{"%" + searchText.getText().toString() + "%"});


    adapter = new CustomSimpleCursor(
            this, 
            R.layout.cook_tab_generalist, 
            cursor, 
            new String[] {"name", "disc", "prep"}, 
            new int[] {R.id.name, R.id.disc, R.id.prep});

    setListAdapter(adapter);}

public void search(View view) {
    // ||Query SQLite
    cursor = db.rawQuery("SELECT _id, name, disc, thumb, prep  FROM mains WHERE name LIKE ?", 
                    new String[]{"%" + searchText.getText().toString() + "%"});

        adapter = new CustomSimpleCursor(
                this, 
                R.layout.cook_tab_generalist, 
                cursor, 

                new String[] {"name", "disc", "prep"}, 
                new int[] {R.id.name, R.id.disc, R.id.prep});
        setListAdapter(adapter);}


public void onListItemClick(ListView parent, View view, int position, long id) {
    Intent intent = new Intent(this, Cook_tab_mains_details.class);
    Cursor cursor = (Cursor) adapter.getItem(position);
    intent.putExtra("MAINS_ID", cursor.getInt(cursor.getColumnIndex("_id")));
    startActivity(intent);
}
}
然后,当选择一个项目时,它会显示此活动中的详细信息:

import java.io.IOException;
import java.io.InputStream;
import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;

public class Cook_tab_mains_details extends Activity {

protected TextView Name;
protected ImageView Photo;
protected TextView Ingredients;
protected TextView HowTo;
protected TextView Information;


protected int mainId;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.cook_tab_generaldetails);

    mainId = getIntent().getIntExtra("MAINS_ID", 0);
    SQLiteDatabase db = (new Cook_tab_mains_data(this)).getWritableDatabase();
    Cursor cursor = db.rawQuery("SELECT emp._id, emp.name, emp.photo, emp.ingre, emp.howto, emp.info, emp.mainId, mgr.name mainsname, mgr.disc mainsdiscname FROM mains emp LEFT OUTER JOIN mains mgr ON emp.mainId = mgr._id WHERE emp._id = ?", 
            new String[]{""+mainId});

    if (cursor.getCount() == 1)
    {
        cursor.moveToFirst();

        Name = (TextView) findViewById(R.id.FoodName);
        Name.setText(cursor.getString(cursor.getColumnIndex("name")));

        Photo = (ImageView) findViewById(R.id.Photo);
        try {
            InputStream bitmap=getAssets().open(cursor.getString(cursor.getColumnIndexOrThrow("photo")));
            Bitmap bit=BitmapFactory.decodeStream(bitmap);
            Photo.setImageBitmap(bit);
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        Ingredients = (TextView) findViewById(R.id.Ingre);
        Ingredients.setText(cursor.getString(cursor.getColumnIndex("ingre")));

        HowTo = (TextView) findViewById(R.id.HowtoDo);
        HowTo.setText(cursor.getString(cursor.getColumnIndex("howto")));

        Information = (TextView) findViewById(R.id.Information);
        Information.setText(cursor.getString(cursor.getColumnIndex("info")));



    } }}
问题是:我似乎无法关闭()数据库。我到处找。我找不到答案。 每次尝试此命令时:

public void close() 
{
    Cook_tab_mains_data.close();
}
它给我这个错误并且不会编译:
无法从类型SQLiteOpenHelper对非静态方法close()进行静态引用

那现在怎么办?
如何关闭我的数据库?

在活动中的onCreate方法的最后,添加
游标。关闭()
db.close()
分别关闭光标和数据库


更可取的是,您应该在onStart方法中加载数据,并在活动的onStop方法中关闭游标+数据库。(但这只是一个建议)

在活动Cook_tab_main_details中的onCreate方法的最后,添加
cursor.close()
db.close()
分别关闭光标和数据库

更可取的是,您应该在onStart方法中加载数据,并在活动的onStop方法中关闭游标+数据库。(但这只是一个建议)

你必须打电话

cursor.close();
当你不再需要它们时。

你必须打电话

cursor.close();
当你不再需要它们时。

在“烹饪”选项卡中添加:

@Override
public void onDestroy() {
    db.close()
}
在烹饪选项卡中添加:

@Override
public void onDestroy() {
    db.close()
}

在安卓系统中,你不需要显式关闭数据库,它会被安卓系统神奇地自动关闭。简而言之,不要担心关闭数据库。
错误是您试图关闭使用ClassName.close()创建的对象,该方法不是静态方法。您可以随时调用
db.close()
,其中db是对象。不过,游标应该由您管理。

在Android中,您不需要显式关闭db。它由Android自动神奇地关闭。简而言之,不要担心关闭数据库。
错误是您试图关闭使用ClassName.close()创建的对象,该方法不是静态方法。您可以随时调用
db.close()
,其中db是对象。不过,游标应该由您管理。

“正如您所看到的,我的数据库是静态的”数据库名称声明为静态的事实并不意味着您的数据库是静态的。“正如您所看到的,我的数据库是静态的”数据库名称声明为静态的事实,这并不意味着你的数据库是静态的。我通过使用@Override public void onDestroy(){super.onDestroy();db.close();cursor.close();}对Cook_tab_main进行修复,然后使用db.close();cursor.close();对于烹饪、标签、电源、细节……它工作得非常完美!!!谢谢,我用@Override public void onDestroy(){super.onDestroy();db.close();cursor.close();}修复了这个问题,然后是db.close();cursor.close();对于烹饪、标签、电源、细节……它工作得非常完美!!!谢谢