在 android 递归调用的 getDatabase 中获取异常

Getting exception in getDatabase called recursively in android

我正在尝试在 android 中为我的项目实现 DBHelper,我是如何实现它的 我想做的是,在运行时决定要为此创建哪个数据库我实现了 class abstract class SQLiteDBService extends SQLiteOpenHelper 它由两个 classes LocalSQLiteDBServiceRestServerSQLiteDBService 运行时继承,我决定调用哪个 override classes 中的 onCreate 方法不同的数据库和表,

package db_service;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.Iterator;
import db_table.TABLES;

/**
 * Created by Dipak on 3/5/2016.
 */
public abstract class SQLiteDBService extends SQLiteOpenHelper{

    private static final String TAG_DB_OPERATION    = "DB Operation";

    private static final int    DATABASE_VERSION = 1;

    private SQLiteDatabase  m_sqlLiteDatabase;

    public SQLiteDBService(Context context,String database_name) {
        super(context, database_name, null, DATABASE_VERSION);
        Log.i(TAG_DB_OPERATION, "Creating Database...");
    }

    public void OpenWrite() {
        m_sqlLiteDatabase = this.getWritableDatabase();
    }

    public void OpenRead() {
        m_sqlLiteDatabase = this.getReadableDatabase();
    }


    public void Close() {
        this.close();
    }

    //TODO:it will get called for every application launch
    public void CreateTable(JSONObject obj) {
        try {
            int i=0;
            JSONObject tables = obj.getJSONObject("tables");
            Log.i(TAG_DB_OPERATION ,"Tables:" + tables.toString());
            Iterator<String> table = tables.keys();
            while(table.hasNext()){
                String tableName = table.next();
                Log.i(TAG_DB_OPERATION,"Table Name:" + tableName);
                JSONArray tableColumns = tables.getJSONArray(tableName);
                Log.i(TAG_DB_OPERATION, "Table Columns:" + tableColumns.toString());
                String create_table_query = "create table " + tableName + "(";
                for(i = 0 ; i < tableColumns.length();i++) {
                    JSONObject column = tableColumns.getJSONObject(i);
                    Log.i(TAG_DB_OPERATION,"Column:" + column.toString());
                    create_table_query += column.getString("name") + " " + column.getString("type");
                    if(i != tableColumns.length()-1){
                        create_table_query += ",";
                    }
                }
                create_table_query += ");";
                CreateTable(create_table_query);
            }
        }
        catch (Exception e) {
            Log.i("DB Operation","Something wrong failed to create table");
        }
    }

    public void CreateTable(String createTableQuery) {
        Log.i(TAG_DB_OPERATION,"CreateTable" +createTableQuery);
        OpenWrite();
        m_sqlLiteDatabase.execSQL(  createTableQuery);
        Log.i(TAG_DB_OPERATION,"Done Creating Table");
    }

    public Cursor ReadTable(String tableName, String[] columns) {
        Log.i(TAG_DB_OPERATION,"ReadTable");
        OpenRead();
        return m_sqlLiteDatabase.query(tableName, columns, null, null, null, null, null);
    }
}

下面是我的 class 的代码,它将覆盖 onCreate 方法

package db_service;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import db_table.TABLES;

/**
 * Created by Dipak on 3/5/2016.
 */
public class LocalSQLiteDBService extends SQLiteDBService {
    private static final String TAG_LOCAL_DB_OPERATION = "DB Operation Local";

    private static final String DATABASE_NAME       = "LOCAL.DB";
    public LocalSQLiteDBService(Context context){
        super(context, DATABASE_NAME);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.i(TAG_LOCAL_DB_OPERATION,"onCreate");
        //CreateTable(TABLES.LOCAL_DB.CREDENTIAL_STORE.getJson());
        CreateTable(TABLES.LOCAL_DB.CREDENTIAL_STORE.CREATE_TABLE_QUERY);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public boolean isCredentialsPresent() {
        Log.i(TAG_LOCAL_DB_OPERATION,"isCredentialsPresent");
        return GetStoredCredentials().getCount() != 0;
    }

    public Cursor GetStoredCredentials(){
        Log.i(TAG_LOCAL_DB_OPERATION,"isCredentialsPresent");
        String[] columns = {
                TABLES.LOCAL_DB.CREDENTIAL_STORE.ID,
                TABLES.LOCAL_DB.CREDENTIAL_STORE.USER_ID,
                TABLES.LOCAL_DB.CREDENTIAL_STORE.PASSWORD
            };
        return ReadTable(TABLES.LOCAL_DB.CREDENTIAL_STORE.CREATE_TABLE_QUERY,columns);
    }
}

下面是我的使用方法

LocalSQLiteDBService m_SqLiteDBServiceLocal;
m_SqLiteDBServiceLocal = new LocalSQLiteDBService(this);
m_SqLiteDBServiceLocal.isCredentialsPresent()

下面是我得到的异常

03-06 14:21:59.816 30879-30879/? I/DB Operation Local: onCreate
03-06 14:21:59.816 30879-30879/? I/DB Operation: CreateTablecreate table credentials_store(id number,user_id number,password text);
03-06 14:21:59.817 30879-30879/? E/AndroidRuntime: FATAL EXCEPTION: main
                                                   Process: com.buk, PID: 30879
                                                   java.lang.RuntimeException: Unable to start activity ComponentInfo{com.buk/com.buk.MainActivity}: java.lang.IllegalStateException: getDatabase called recursively
                                                       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
                                                       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
                                                       at android.app.ActivityThread.-wrap11(ActivityThread.java)
                                                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
                                                       at android.os.Handler.dispatchMessage(Handler.java:102)
                                                       at android.os.Looper.loop(Looper.java:148)
                                                       at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                                                    Caused by: java.lang.IllegalStateException: getDatabase called recursively
                                                       at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:203)
                                                       at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
                                                       at db_service.SQLiteDBService.OpenWrite(SQLiteDBService.java:33)
                                                       at db_service.SQLiteDBService.CreateTable(SQLiteDBService.java:77)
                                                       at db_service.LocalSQLiteDBService.onCreate(LocalSQLiteDBService.java:25)
                                                       at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:251)
                                                       at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
                                                       at db_service.SQLiteDBService.OpenRead(SQLiteDBService.java:37)
                                                       at db_service.SQLiteDBService.ReadTable(SQLiteDBService.java:84)
                                                       at db_service.LocalSQLiteDBService.GetStoredCredentials(LocalSQLiteDBService.java:45)
                                                       at db_service.LocalSQLiteDBService.isCredentialsPresent(LocalSQLiteDBService.java:35)
                                                       at com.buk.MainActivity.onCreate(MainActivity.java:51)
                                                       at android.app.Activity.performCreate(Activity.java:6237)
                                                       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
                                                       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
                                                       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
                                                       at android.app.ActivityThread.-wrap11(ActivityThread.java) 
                                                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
                                                       at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                       at android.os.Looper.loop(Looper.java:148) 
                                                       at android.app.ActivityThread.main(ActivityThread.java:5417) 
                                                       at java.lang.reflect.Method.invoke(Native Method) 
                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

如果 getWritableDB 已经被调用但没有关闭原始的,则不能调用它。在 onCreate 中,您传递了一个可写的数据库。使用那个,并将其传递给您的辅助函数。没有你的辅助函数请求一个新的。