泄漏发现SQL数据库永远不会关闭

时间:2012-04-15 21:01:03

标签: 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 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();
}

它给了我这个错误,不会编译:{{1​​}}

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

4 个答案:

答案 0 :(得分:2)

在活动 Cook_tab_mains_details onCreate 方法的最后,添加cursor.close();db.close()以分别关闭游标和数据库。< / p>

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

答案 1 :(得分:1)

在Android中你不需要显式关闭数据库。它是由android自动神奇地关闭的。简而言之,不要担心关闭db。

错误是您尝试使用ClassName.close()关闭您创建的对象,这不是一个静态方法。您可以随时调用db.close(),其中db是对象。游标应该由你管理。

答案 2 :(得分:0)

你必须致电

cursor.close();

当你不再需要它们时。

答案 3 :(得分:0)

在Cook_tab_mains中添加:

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