2

我正在开发一个待办事项列表应用程序,以了解有关 Android 应用程序开发过程的更多信息。我正在关注一个在线教程,但我似乎遇到了 SQLite 数据库的错误。它编译得很好,但是一旦运行就会强制关闭。这是 logcat 输出:

I/SQLiteConnectionPool(24686): The connection pool for /data/data/com.rohan.todo/databases/taskerManager has been closed but there are still 1 connections in use.  They will be closed as they are released back to the pool.
D/AndroidRuntime(24686): Shutting down VM
W/dalvikvm(24686): threadid=1: thread exiting with uncaught exception (group=0x410e3930)
E/AndroidRuntime(24686): FATAL EXCEPTION: main
E/AndroidRuntime(24686): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.rohan.todo/com.rohan.todo.ViewTask}: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/com.rohan.todo/databases/taskerManager
E/AndroidRuntime(24686):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2306)
E/AndroidRuntime(24686):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2356)
E/AndroidRuntime(24686):    at android.app.ActivityThread.access$600(ActivityThread.java:150)
E/AndroidRuntime(24686):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1244)
E/AndroidRuntime(24686):    at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(24686):    at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime(24686):    at android.app.ActivityThread.main(ActivityThread.java:5195)
E/AndroidRuntime(24686):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(24686):    at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime(24686):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
E/AndroidRuntime(24686):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
E/AndroidRuntime(24686):    at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime(24686): Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/com.rohan.todo/databases/taskerManager
E/AndroidRuntime(24686):    at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
E/AndroidRuntime(24686):    at android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:520)
E/AndroidRuntime(24686):    at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:263)
E/AndroidRuntime(24686):    at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
E/AndroidRuntime(24686):    at com.rohan.todo.TaskerDbHelper.getAllTasks(TaskerDbHelper.java:70)
E/AndroidRuntime(24686):    at com.rohan.todo.ViewTask.onCreate(ViewTask.java:32)
E/AndroidRuntime(24686):    at android.app.Activity.performCreate(Activity.java:5104)
E/AndroidRuntime(24686):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
E/AndroidRuntime(24686):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2260)
E/AndroidRuntime(24686):    ... 11 more

这是我的代码:

ViewTask.java

package com.rohan.todo;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class ViewTask extends Activity {
    protected TaskerDbHelper db;
    List<Task> list;
    MyAdapter adapt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_task);
        db = new TaskerDbHelper(this);
        list = db.getAllTasks();
        adapt = new MyAdapter(this, R.layout.list_inner_view, list);
        ListView listTask = (ListView) findViewById(R.id.listView1);
        listTask.setAdapter(adapt);
    }

    public void addTaskNow(View v) {
        EditText t = (EditText) findViewById(R.id.editText1);
        String s = t.getText().toString();
        if (s.equalsIgnoreCase("")) {
            Toast.makeText(this, "enter the task description first!!",
                    Toast.LENGTH_LONG);
        } else {
            Task task = new Task(s, 0);
            db.addTask(task);
            Log.d("tasker", "data added");
            t.setText("");
            adapt.add(task);
            adapt.notifyDataSetChanged();
        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_view_task, menu);
        return true;
    }

    private class MyAdapter extends ArrayAdapter<Task> {

        Context context;
        List<Task> taskList = new ArrayList<Task>();
        int layoutResourceId;

        public MyAdapter(Context context, int layoutResourceId,
                List<Task> objects) {
            super(context, layoutResourceId, objects);
            this.layoutResourceId = layoutResourceId;
            this.taskList = objects;
            this.context = context;
        }

        /**
         * This method will DEFINe what the view inside the list view will
         * finally look like Here we are going to code that the checkbox state
         * is the status of task and check box text is the task name
         */
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            CheckBox chk = null;
            if (convertView == null) {
                LayoutInflater inflater = (LayoutInflater) context
                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.list_inner_view,
                        parent, false);
                chk = (CheckBox) convertView.findViewById(R.id.chkStatus);
                convertView.setTag(chk);

                chk.setOnClickListener(new View.OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        CheckBox cb = (CheckBox) v;
                        Task changeTask = (Task) cb.getTag();
                        changeTask.setStatus(cb.isChecked() == true ? 1 : 0);
                        db.updateTask(changeTask);
                        Toast.makeText(
                                getApplicationContext(),
                                "Clicked on Checkbox: " + cb.getText() + " is "
                                        + cb.isChecked(), Toast.LENGTH_LONG)
                                .show();
                    }

                });
            } else {
                chk = (CheckBox) convertView.getTag();
            }
            Task current = taskList.get(position);
            chk.setText(current.getTaskName());
            chk.setChecked(current.getStatus() == 1 ? true : false);
            chk.setTag(current);
            Log.d("listener", String.valueOf(current.getId()));
            return convertView;
        }

    }

}

任务.java

package com.rohan.todo;

public class Task {
    private String taskName;
    private int status;
    private int id;

    public Task()
    {
        this.taskName=null;
        this.status=0;
    }
    public Task(String taskName, int status) {
        super();
        this.taskName = taskName;
        this.status = status;
    }

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getTaskName() {
        return taskName;
    }
    public void setTaskName(String taskName) {
        this.taskName = taskName;
    }
    public int getStatus() {
        return status;
    }
    public void setStatus(int status) {
        this.status = status;
    }

}

任务DBHelper.java

package com.rohan.todo;

import java.util.ArrayList;
import java.util.List;

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

public class TaskerDbHelper extends SQLiteOpenHelper {

    private static final int DATABASE_VERSION = 1;

    // Database Name
    private static final String DATABASE_NAME = "taskerManager";

    // tasks table name
    private static final String TABLE_TASKS = "tasks";

    // tasks Table Columns names
    private static final String KEY_ID = "id";
    private static final String KEY_TASKNAME = "taskName";
    private static final String KEY_STATUS = "status";

    public TaskerDbHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        String sql = "CREATE TABLE IF NOT EXISTS " + TABLE_TASKS + " ( "
                + KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + KEY_TASKNAME
                + " TEXT, " + KEY_STATUS + " INTEGER)";
        db.execSQL(sql);

        db.close();
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldV, int newV) {
        // Drop older table if existed
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_TASKS);
        // Create tables again
        onCreate(db);
    }

    // Adding new task
    public void addTask(Task task) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_TASKNAME, task.getTaskName()); // task name
        // status of task- can be 0 for not done and 1 for done
        values.put(KEY_STATUS, task.getStatus());

        // Inserting Row
        db.insert(TABLE_TASKS, null, values);
        db.close(); // Closing database connection
    }

    public List<Task> getAllTasks() {
        List<Task> taskList = new ArrayList<Task>();
        // Select All Query
        String selectQuery = "SELECT  * FROM " + TABLE_TASKS;

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        // looping through all rows and adding to list
        if (cursor.moveToFirst()) {
            do {
                Task task = new Task();
                task.setId(cursor.getInt(0));
                task.setTaskName(cursor.getString(1));
                task.setStatus(cursor.getInt(2));
                // Adding contact to list
                taskList.add(task);
            } while (cursor.moveToNext());
        }

        // return task list
        return taskList;
    }

    public void updateTask(Task task) {
        // updating row
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(KEY_TASKNAME, task.getTaskName());
        values.put(KEY_STATUS, task.getStatus());
        db.update(TABLE_TASKS, values, KEY_ID + " = ?",new String[] {String.valueOf(task.getId())});
        db.close();
    }
}

如果有人可以帮助我找到代码中的错误并提出修复建议,我将不胜感激!非常感谢您帮助像我这样的菜鸟:)

4

2 回答 2

1

正如我在评论中所说,您应该从 onCreate(SQLiteDatabase db) 函数中删除以下内容

删除以下函数中的 db.close()

     @Override
     public void onCreate(SQLiteDatabase db) {

    String sql = "CREATE TABLE IF NOT EXISTS " + TABLE_TASKS + " ( "
            + KEY_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + KEY_TASKNAME
            + " TEXT, " + KEY_STATUS + " INTEGER)";
    db.execSQL(sql);

    //db.close(); // remove this line
  } 

编辑:

将此添加到您的数据库助手类中。当您关闭时,您可以调用此函数。

     public TaskerDbHelper open()throws SQLException
    {

    ourDatabase= this.getWritableDatabase();
    return this;
    }

更新

    db = new TaskerDbHelper(this);
    db.open();   
    db.updateTask(changeTask); 
于 2013-06-07T19:42:02.287 回答
0

在更新并插入 addTask() 函数后,您不需要在 onCreate() 函数中调用 db.close。永远不要关闭数据库。完全没有。从代码中删除db.close();行。

于 2013-06-07T19:39:49.963 回答