【问题标题】:Android IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase [duplicate]Android IllegalStateException:尝试重新打开已经关闭的对象:SQLiteDatabase [重复]
【发布时间】:2013-04-04 22:26:25
【问题描述】:

我知道有几个像这样的问题,但他们似乎都有不同的方法来解决问题,没有一个解决了我的问题。

我的主要活动工作正常,加载数据库并填充列表视图。然后我调用第二个活动,当我尝试加载列表视图时问题出现了。

我尝试过使用start/stop managingcursor(cursor),尽管它已被弃用,但它并没有解决问题。此外,我尝试在我的主要活动中关闭光标和数据库,然后再触发下一个活动,但这也无济于事。

两个类都继承自 ListActivity 并遵循相同的顺序:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);        

    //Open db in writing mode
    MySQLiteHelper.init(this);
    MySQLiteHelper tpdbh =
        new MySQLiteHelper(this, "DB", null, 1);


    SQLiteDatabase db = tpdbh.getWritableDatabase();

    checkLocationAndDownloadData(); //this fires a Asynctask that calls method parseNearbyBranches shown bellow

   //I load the data to the ListView in the postExecute method of the asynctask by calling:
    /*
    Cursor cursor = MysSQLiteHelper.getBranchesNames();
    adapter = new SimpleCursorAdapter(this,
            R.layout.row, cursor, fields, new int[] { R.id.item_text },0);
    setListAdapter(adapter);
    */

    ListView lv = getListView();
    lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
     @Override
        public void onItemClick(AdapterView<?> listView, View view,
            int position, long id) {

         // Get the cursor, positioned to the corresponding row in the result set
         Cursor cursor = (Cursor) listView.getItemAtPosition(position);

       // Get the state's capital from this row in the database.
       String branch_id = cursor.getString(cursor.getColumnIndexOrThrow("branch_id"));

           cursor.close();

        openNextActivity(Integer.parseInt(branch_id));
        }
      });
}

//在另一个文件中:

private void parseNearbyBranches(JSONObject jo) throws JSONException
{
 if (   jo.has(jsonTitle) && 
            jo.has("company_id") &&
            jo.has("id")
    ) {
        String branch = jo.getString(jsonTitle);


            MySQLiteHelper tpdbh = MySQLiteHelper.instance;
            SQLiteDatabase db = tpdbh.getWritableDatabase();

            db.execSQL("INSERT INTO Branches (branch_id, name, company_id) " +
                    "VALUES ('" +jo.getInt("id")+"', '" + branch +"', '" +jo.getInt("company_id")+"' )");

            db.close(); //no difference is I comment or uncomment this line

    }
}

在 MySQLiteHelper.java 中:

public static Cursor getBranchesNames() {
        // TODO Auto-generated method stub
        String[] columns = new String[] { "_id", "branch_id", "name", "company_id" };
        Cursor c = getReadDb().query(branchesTable, columns, null, null, null, null,
                null);            
        return c;
    }

我的其他活动基本相同:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_branch_surveys);

    //Read branch data from DB
        int companyID = -1;
        MySQLiteHelper.init(this);          

        String [] columns = new String [] {"company_id"};
        String [] args = {Integer.toString(branchID)};
        Cursor c = MySQLiteHelper.getReadDb().query(MySQLiteHelper.branchesTable, columns, "branch_id=?", args, null, null, null); //THIS QUERY WORKS JUST FINE

        if (c.moveToFirst())
            companyID = Integer.parseInt(c.getString(0));
        c.close();

        if( companyID != -1)
        {
            new DownloadTask().execute(Integer.toString(companyID) );
//where the Async task calls something just like NearByBranches shown above(but with different  objects of course)
//And the postExecute sets the listView:
/*  cursor = MySQLiteHelper.getAll();
    SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
            R.layout.row, cursor, fields, new int[] { R.id.item_text },0);
    setListAdapter(adapter);  
*/
        }

    }
}

在 MySQLiteHelper.java 中:

public static Cursor getAll() {
    // TODO Auto-generated method stub
    String[] columns = new String[] { "_id","title", "points" };

//********IT IS IN THIS LINE WHERE I GET THE ERROR:********************
    Cursor c = getReadDb().query(theTable, columns, null, null, null, null,
            null);

    return c;
}

  public static SQLiteDatabase getReadDb() {
        if (null == db) {
            db = instance.getReadableDatabase();
        }
        return db;
    }

我希望你能帮助我。谢谢!

【问题讨论】:

  • 什么是getReadDb()?我认为这很简单。
  • 我已经用 'getReadDb()' 方法更新了这个问题。基本上是'instance.getReadableDatabase();' sqlite数据库的
  • 想是这样,但想确定一下。你在那个班级的任何地方都打电话给db.close()吗?还是您保存对database = getReadDb() 的引用并调用database.close()
  • 不在那个班级。我在 parseNearbyBranches() 中调用 db.close() 并在我在新活动中调用的类似方法中调用
  • 我现在感觉很傻。。我只是尝试在 parseNeabyBranches 的类似方法中评论 db.close,问题就解决了。然而,在 parseNearbyBranches() 中使用 db.close() 时我没有得到同样的错误,你能解释一下为什么吗? (请这样做作为答案,以便我可以将其标记为已解决)

标签: android android-sqlite


【解决方案1】:

我刚刚尝试在 parseNeabyBranches 的类似方法中评论 db.close,问题就解决了。然而,在 parseNearbyBranches() 中使用 db.close() 时我没有得到同样的错误,你能解释一下为什么吗?

parseNearbyBranches() 中创建一个单独的 SQLiteDatabase 对象:

SQLiteDatabase db = tpdbh.getWritableDatabase();

由于这是与getReadDb() 返回的对象不同的对象,因此您可以(并且应该)关闭它。基本规则是每次调用getWritableDatabase()getReadableDatable() 时,都必须有一个匹配的close() 语句。

【讨论】:

  • 我被屏蔽了,虽然我也在其他类似的地方创建了一个新的 SQLiteDatabase。它实际上与 parseNearbyBranches 相同,但具有不同的 JSON 对象和不同的查询。
  • 嗯,代码在你的问题中吗?我想看看它们,也许这是您创建 MySQLHelper 的方式......看起来您正试图为所有类使用一个实例。
  • 这里是另一种方法的代码:pastie.org/7328674
  • 这很奇怪,我看不出有什么明显的区别可以解释...我很高兴我们解决了这个错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-28
相关资源
最近更新 更多