android - 尝试重新打开已经关闭的对象...地狱消息

时间:2018-01-19 04:47:01

标签: android sqlite database-connection adapter sqliteopenhelper

在某些段落中,我遇到了sqllite错误"打开连接已打开" ...好吧,实际上我并不忙于总是关闭连接,因为我已经读过,如果操作不是很大的话,建议不要这么做......但显然并不总是这样......或者不是吗?我在这一点上感到困惑....

为了解决这个问题,我在每个使用其适配器执行数据库操作的活动中插入了此代码:

@Override
protected void onDestroy ()
{
super.onDestroy ();
mDbHelper.closeConnection ();
}

这已经解决了所有问题,而且一切都已经解决了好几个月。

现在实施其他我收到此错误:

"尝试重新打开已关闭的对象,然后关闭数据库"

一个'活动通过OnActivityForResult调用另一个活动但是"某人或某事" (我假设低级别的android)调用我的" OnDestroy" (要关闭连接)...触发我发现的错误的原因但是我不知道如何干预......我不是那个叫OnDestroy而是Android的人...它是怎么来的出?

现在(在我调用另一个活动的情况下)我已经绕过了这样的问题:

@Override
protected void onDestroy ()
{
if (! m_Modality.equalsIgnoreCase ("MYCALLBACK"))
{
mDbHelper.closeConnection ();
}
}

但我不喜欢它,我想一​​劳永逸地理解你是如何在这个sqlite上工作的......

  • 如果由于有关是否已经打开的消息而不必关闭连接?

  • 如果我关闭它,因为消息说它刚刚关闭了?

  • 如果ANDROID调用我插入连接闭包的方法,因为我无法以明确的方式管理事物?

我希望有人能澄清我的想法......

2 个答案:

答案 0 :(得分:0)

我建议不要尝试关闭连接/数据库,因为打开数据库资源非常昂贵(参见下面的引文)并且经常是不可靠的。可能只是在主要活动onDestroy中关闭它,也许与使用单一的SQLiteDatabase /连接相结合。

游标虽然应该在完成时总是关闭,但太多打开会导致异常。我遵循规则,如果它们仅在方法中使用,则在方法内关闭。如果它们被活动的UI(例如Spinner,ListView等)使用,则关闭活动onDestroy中的光标。如果它们是在循环中创建的,那么在完成它们后立即关闭它们。

  

因为getWritableDatabase()和getReadableDatabase()很昂贵   在数据库关闭时调用,您应该离开数据库   只要您可能需要访问它,连接就会打开。   通常,最好在onDestroy()中关闭数据库   调用Activity。 Persisting Database Connection

  

关闭连接会丢弃页面缓存,并且需要这样做   检查模式版本并重新解析整个模式   下次打开。

     

在大多数应用程序中,没有足够的数据库访问权限   实际上会不断重新打开数据库的开销   显。但是没有理由在您的应用中添加无用的代码。

     

请注意,SQLiteDatabase对象是引用计数的。因此,如果   如果您正在使用全局打开帮助程序实例,则可以保持数据库打开   使用额外的getWritableDatabase()调用,即使是所有其他调用   代码调用close()。 CL's answer

您可能还希望阅读Using Singleton design pattern for SQLiteDatabase

答案 1 :(得分:0)

在某些情况下,例如,你在另一个函数中传递游标结果是不可能关闭游标(你必须传递一个游标而不是null),我总是尝试创建一个'read'o'过滤器'模板函数和在最后我关闭光标但不是全部...这对于所有情况都是不可能的...这取决于我的堆栈周期,对于任何情况都不同,它是一个大应用程序,30 sqliteadapter交互......我认为它是一个错误迫使开发人员总是以不同的模式关闭和打开;如果我打开并重新关闭连接,那么sqlite会生成错误...内存?...这是复杂的应用程序中的地狱......我读了你的链接信息,现在谢谢!

这是我的代码: (我有一个界面自定义基础但不重要)

@Override
    public Cursor fetchFiltro(String filtroWhere) {
        Cursor mycursor =null;
        try {
            openConnection();
            mycursor = getDatabase().query(true, getNomeTab(),
                    new String[]  { COL_ID, COL_CODICE, COL_DESCRIZIONE,COL_PREZZOACQ,COL_PREZZOVEN, COL_CODICEUMISURA, COL_CODICEUMISURACONF, COL_QTA, COL_CODICECATEGORIA,COL_CODICEIVA,  COL_FORNITORE,  COL_CODICEFORNITORE, COL_ORDINEMINIMO,
                COL_DATAINSERIMENTO},   
                filtroWhere, null, null, null, COL_DATAINSERIMENTO +" desc", null );

            return mycursor;
        }
        catch (Exception e) 
        {
            Toast.makeText(MyApp.getContext(), e.getMessage(),Toast.LENGTH_LONG).show();
            UtiLog.WriteLogOnTop(mClassName + ".fetchFiltro() " +   e.getMessage().toString(),UtiLog.ERROR);
            if (!(mycursor==null)) {mycursor.close();}
            return null;
        }

        finally 
        {

        }
    }

我致电:

public List<Articolo>  dammiListaArticoliDaSqlWhere( String prm_sqlWhere  ) 
{

    List<Articolo> listaArticoli= new ArrayList<Articolo>();

    Cursor cursor = fetchFiltro(prm_sqlWhere);
    if( cursor != null )
    {
        while ( cursor.moveToNext() ) 
        {
            Articolo articolo = getArticolo(cursor);
            listaArticoli.add( articolo );
        } 
        cursor.close();
    }
    return listaArticoli;   
}

我的openConnection()调用dbHelper类函数:

public void openConnection() throws SQLException 
    {
        dbHelper.openConnection();
    }

OpenConnection的代码:

public void openConnection() throws SQLException 
    {
        if (getDatabase()==null)
        {
            setDatabase( getWritableDatabase() );       
        }
    }

  private void setDatabase(SQLiteDatabase database) 
    {
    this.database = database;
    }

它工作得很完美......只有当操作系统(主动)调用活动的OnDestroy(我必须插入closeconnection())时才会出现问题...我无法删除那个紧密连接( ),如果我在其他活动中删除它,它给我的消息“数据库已经打开”....我无法摆脱这种情况,我总是被迫手动将一些代码放到手中,从大小写到这是令人沮丧的。 再次感谢