java - Android Studio - 尝试重新打开已关闭的对象: SQLiteDatabase

标签 java android sql sqlite

我正在制作我的第一个 Android 应用程序,在使用 Java 方面我完全是个新手,因为我只使用过 Python。我正在尝试创建一个通过初始设置 Activity 存储用户详细信息的数据库,但是出现错误

08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:  Caused by:        java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/user/0/fitness.essentials.fitnessessentials/databases/UserData.db
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:525)
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:262)
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at fitness.essentials.fitnessessentials.Database.<init>(Database.java:26)
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at fitness.essentials.fitnessessentials.SetupScreen.onCreate(SetupScreen.java:44)
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at android.app.Activity.performCreate(Activity.java:6876)
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1135)
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3206)
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3349) 
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at android.app.ActivityThread.access$1100(ActivityThread.java:221) 
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794) 
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:102) 
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:158) 
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:7224) 
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method) 
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
08-13 17:24:27.400 10263-10263/? E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 

这是数据库类的主要部分

// Constructor method
    public Database(Context context) {
    // Superclass constructor called to create database
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
    onCreate(this.getWritableDatabase());
}

// On create the databases are created (if they don't exist)
public void onCreate(SQLiteDatabase db) {
    db.execSQL(SQL_CREATE_USER);
    db.close();
}

// Currently no special treatment for upgrading or downgrading the schema
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  }
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {  }


/*               Shorthand methods for generic tasks              */
// Add a single row of user data
public long addUserData(String name, String gender, String dob, String height, float currentweightNum,
                        float targetweightNum, String activitylevel, String weightdifference) {
    // Get database that is readable
    SQLiteDatabase db = this.getWritableDatabase();

    // Define row values
    ContentValues values = new ContentValues();
    values.put(DataContract.UserColumns.COLUMN_NAME, name);
    values.put(DataContract.UserColumns.COLUMN_GENDER, gender);
    values.put(DataContract.UserColumns.COLUMN_DOB, dob);
    values.put(DataContract.UserColumns.COLUMN_HEIGHT, height);
    values.put(DataContract.UserColumns.COLUMN_CURRENT_WEIGHT, currentweightNum);
    values.put(DataContract.UserColumns.COLUMN_TARGET_WEIGHT, targetweightNum);
    values.put(DataContract.UserColumns.COLUMN_ACTIVITY_LEVEL, activitylevel);
    values.put(DataContract.UserColumns.COLUMN_WEIGHT_DIFFERENCE, weightdifference);


    // Insert values into the database, in the user data table
    long newRowId = db.insert(
            DataContract.UserColumns.TABLE_NAME,
            null,
            values);

    db.close();
    // Return the row id that the data was inserted into
    return newRowId;
}

这是我试图添加详细信息的设置屏幕类

public class SetupScreen extends AppCompatActivity implements AdapterView.OnItemSelectedListener {

private String Name;
private String Gender;
private String Height;
private String CurrentWeight;
private String TargetWeight;
private String DOB;
private String ActivityLevel;
private String WeightDifference;

private Database dbhelper;




@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_setup_screen);
    Name = "";
    Gender = "";
    Height = "";
    CurrentWeight = "";
    TargetWeight = "";
    DOB = "";
    ActivityLevel = "";
    WeightDifference = "";


    dbhelper = new Database(getApplicationContext());





    Spinner spinnerGender = (Spinner) findViewById(R.id.spinnerGender);

    ArrayAdapter<CharSequence> adapterGender = ArrayAdapter.createFromResource(this,
            R.array.gender, android.R.layout.simple_spinner_item);
    adapterGender.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinnerGender.setAdapter(adapterGender);

    spinnerGender.setOnItemSelectedListener(this);

    Spinner spinnerActivityLevel = (Spinner) findViewById(R.id.spinnerActivityLevel);

    ArrayAdapter<CharSequence> adapterActivity = ArrayAdapter.createFromResource(this,
            R.array.activity_level, android.R.layout.simple_spinner_item);
    adapterActivity.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinnerActivityLevel.setAdapter(adapterActivity);

    spinnerActivityLevel.setOnItemSelectedListener(this);

    Spinner spinnerWeightDifference = (Spinner) findViewById(R.id.spinnerWeightDifference);

    ArrayAdapter<CharSequence> adapterWeight = ArrayAdapter.createFromResource(this,
            R.array.weight_difference, android.R.layout.simple_spinner_item);
    adapterWeight.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinnerWeightDifference.setAdapter(adapterWeight);

    spinnerWeightDifference.setOnItemSelectedListener(this);



}

public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    Gender = parent.getItemAtPosition(position).toString();
    ActivityLevel = parent.getItemAtPosition(position).toString();
    WeightDifference = parent.getItemAtPosition(position).toString();
}

public void onNothingSelected(AdapterView<?> parent) {
    // An interface callback
}

public void save(View view) {


    Name = ((EditText)findViewById(R.id.Name)).getText().toString();
    DOB = ((EditText)findViewById(R.id.DOB)).getText().toString();
    Height = ((EditText)findViewById(R.id.Height)).getText().toString();
    CurrentWeight = ((EditText)findViewById(R.id.CurrentWeight)).getText().toString();
    TargetWeight = ((EditText)findViewById(R.id.TargetWeight)).getText().toString();


    if (Name.isEmpty()){
        Toast.makeText(getApplicationContext(), "Name cannot be empty!", Toast.LENGTH_LONG).show();
        return;
    }
    if (Gender.isEmpty()){
        Toast.makeText(getApplicationContext(), "Gender cannot be empty!", Toast.LENGTH_LONG).show();
        return;
    }
    if (DOB.isEmpty()){
        Toast.makeText(getApplicationContext(), "DOB cannot be empty!", Toast.LENGTH_LONG).show();
        return;
    }
    if (Height.isEmpty()){
        Toast.makeText(getApplicationContext(), "Height cannot be empty!", Toast.LENGTH_LONG).show();
        return;
    }
    if (CurrentWeight.isEmpty()){
        Toast.makeText(getApplicationContext(), "Current weight cannot be empty!", Toast.LENGTH_LONG).show();
        return;
    }
    Float CurrentWeightNum = Float.parseFloat(CurrentWeight);
    if (CurrentWeightNum < 43.0){
        Toast.makeText(getApplicationContext(), "Your current weight is not supported by this application", Toast.LENGTH_LONG).show();
        return;
    }

    if (TargetWeight.isEmpty()){
        Toast.makeText(getApplicationContext(), "Target weight cannot be empty!", Toast.LENGTH_LONG).show();
        return;
    }
    Float TargetWeightNum = Float.parseFloat(TargetWeight);
    if (TargetWeightNum > 93.0){
        Toast.makeText(getApplicationContext(), "Your target weight is not supported by this application", Toast.LENGTH_LONG).show();
        return;
    }
    if (ActivityLevel.isEmpty()){
        Toast.makeText(getApplicationContext(), "Activity level cannot be empty!", Toast.LENGTH_LONG).show();
        return;
    }
    if (WeightDifference.isEmpty()){
        Toast.makeText(getApplicationContext(), "Weight difference cannot be empty!", Toast.LENGTH_LONG).show();
        return;
    }

    if (CurrentWeightNum.equals(TargetWeightNum)){
        Toast.makeText(getApplicationContext(), "Current and target weight can not be the same!", Toast.LENGTH_LONG).show();
        return;
    }

    dbhelper.addUserData(Name, Gender, DOB, Height, CurrentWeightNum, TargetWeightNum, ActivityLevel, WeightDifference);

    Toast.makeText(getApplicationContext(), "You have been saved!", Toast.LENGTH_LONG).show();

    Intent intent = new Intent(this, MainActivity.class);
    startActivity(intent);


}

}

抱歉,如果格式不正确,应用程序当前无法打开,但是当我删除设置屏幕类中的 dbhelper 内容时,应用程序会运行,但当我尝试按 Enter 键调用添加数据方法时,应用程序会崩溃。我已经调查了这个问题,但看不出哪里出了问题。 谢谢

最佳答案

尝试删除:

public void onCreate(SQLiteDatabase db) {
    db.execSQL(SQL_CREATE_USER);
    db.close(); // remove this line
}

还有这个:

onCreate(this.getWritableDatabase());

在 onUpgrade() 方法中添加:

db.execSQL("DROP TABLE IF EXISTS " + YOUR_TABLE_NAME);
onCreate(db);

关于java - Android Studio - 尝试重新打开已关闭的对象: SQLiteDatabase,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38937422/

相关文章:

java - 在 Java 中转换整数字符串时出现 NumberFormatException

java - 对象保留在内存中直到强制 GC

java - 为什么无法访问 Choreographer 类中的 getFrameTime() ?

mysql - 高级 SQL 选择查询/动态列

java - 牛顿法计算速率

android - gridview 位置内的嵌套 ScrollView 只占一部分

java - Android Lollipop java.lang.SecurityException : Neither user nor current process has android. permission.BLUETOOTH_PRIVILEGED

python - 将 SQL 语句存储在属性文件中以供 Python 脚本使用?

mysql - 如何在单个查询中统计与基表结果匹配的多个表的记录?

java - 带按钮的Android自定义对话框