在Android中对数据库构造函数调用getWritableDatabase()时,应用程序崩溃

mklgxw1f  于 2023-03-16  发布在  Android
关注(0)|答案(2)|浏览(237)

我刚刚发现我的应用程序保持崩溃时,我调用了我的数据库类中的getWritableDatabase()方法。以下是我的代码:
主要活动:

package com.google.assignment_lab;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.google.assignment_lab.database.UserTable;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    Button mainRegisterButton, mainLoginButton;
    UserTable userTable = new UserTable(this);
    @Override

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

        mainRegisterButton = findViewById(R.id.mainRegisterButton);
        mainLoginButton = findViewById(R.id.mainLoginButton);
        mainRegisterButton.setOnClickListener(this);
        mainLoginButton.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        Intent intent;

        if(view == mainRegisterButton){
            intent = new Intent(this, RegisterActivity.class);
            startActivity(intent);
        }

        if(view == mainLoginButton){
            intent = new Intent(this, LoginActivity.class);
            startActivity(intent);
        }
    }
}

UserTable.java:

package com.google.assignment_lab.database;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import androidx.annotation.Nullable;

public class UserTable  extends SQLiteOpenHelper {

    public static String DATABASE_NAME = "MyData";
    public static int DATABASE_VERSION = 1;
    public static String TABLE_NAME = "Users";
    Context context;
    SQLiteDatabase database;

    public UserTable(@Nullable Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        this.context = context;
        database = getWritableDatabase();
        database = getReadableDatabase();
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        String query = "CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (username TEXT, password TEXT, email TEXT, phone TEXT)";
        sqLiteDatabase.execSQL(query);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}

我尝试删除getWritableDatabase()和getReadableDatabase(),应用程序工作正常。但问题是,我的用户表从未创建为onCreate方法。我该如何解决这个问题?
错误日志:

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.google.assignment_lab, PID: 8732
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.google.assignment_lab/com.google.assignment_lab.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File android.content.Context.getDatabasePath(java.lang.String)' on a null object reference
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3551)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3782)
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:201)
    at android.os.Looper.loop(Looper.java:288)
    at android.app.ActivityThread.main(ActivityThread.java:7872)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File android.content.Context.getDatabasePath(java.lang.String)' on a null object reference
    at android.content.ContextWrapper.getDatabasePath(ContextWrapper.java:380)
    at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:370)
    at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:316)
    at com.google.assignment_lab.database.UserTable.<init>(UserTable.java:20)
    at com.google.assignment_lab.MainActivity.<init>(MainActivity.java:16)
    at java.lang.Class.newInstance(Native Method)
    at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:95)
    at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
    at android.app.Instrumentation.newActivity(Instrumentation.java:1339)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3538)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3782) 
    at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2307) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loopOnce(Looper.java:201) 
    at android.os.Looper.loop(Looper.java:288) 
    at android.app.ActivityThread.main(ActivityThread.java:7872) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936) 
insrf1ej

insrf1ej1#

我不知道你为什么要把getWritableDatabase()getReadableDatabase()赋值给同一个变量。我最近也在使用DbHandlers,根据我的经验,我通常创建**单独的方法 *(在本地定义)***用于阅读和获取数据:-
示例:-

public void addQuestionToDatabase(Context context, Question question){
        SQLiteDatabase db = getWritableDatabase();

        // Whatever ur code is

        Toast.makeText(context, "Added to database", Toast.LENGTH_SHORT).show();
    }

还有这个

public ArrayList<Question> fetchRecords(Context context){
        ArrayList<Question> questionsSet = new ArrayList<Question>();
        SQLiteDatabase db = getReadableDatabase();

        //Your code here

        return questionsSet;
    }

旁注;***不要***添加db.close(),如果你确定你会多次调用这些方法。

omqzjyyz

omqzjyyz2#

问题是您在SQLiteOpenHelper子类的构造函数中调用getWritableDatabase(),这个构造函数在调用onCreate()之前发生,所以数据库还没有创建。
相反,您应该在代码的另一部分调用getWriteableDatabase(),例如在Activity或Fragment中创建SQLiteOpenHelper的示例。
顺便说一句,我建议你看看API,这是一个非常强大的数据库访问库,这是一种现代的访问方式。

相关问题