You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio读取现有SQLite数据库调用getData方法启动Activity报错如何修复

问题修复方案

问题根因

你代码里的核心问题有以下几个:

  • 数据库路径硬编码不符合安卓系统规范,高版本安卓或多用户设备会出现路径找不到的问题
  • 数据库创建流程存在锁库风险,调用getReadableDatabase()后未及时关闭导致复制数据库失败
  • MainActivity重复初始化数据库工具类,属于无意义的重复操作
  • 获取查询游标后未做异常处理和资源释放,容易触发崩溃和内存泄漏

修复代码

1. 修复DataBaseHelper类

package com.example.cyberartillery;

import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.File;

public class DataBaseHelper extends SQLiteOpenHelper {

    private static String DB_NAME = "northwind";
    private SQLiteDatabase myDataBase;
    private final Context mContext;
    // 动态获取数据库路径,避免硬编码错误
    private String DB_PATH;

    public DataBaseHelper(Context context) {
        super(context, DB_NAME, null, 1);
        this.mContext = context;
        DB_PATH = context.getDatabasePath(DB_NAME).getParent() + "/";
    }

    public void createDataBase() throws IOException {
        boolean dbExist = checkDataBase();

        if(dbExist){
            //数据库已存在,无需操作
        }else{
            this.getReadableDatabase();
            // 新增关闭逻辑,避免锁库导致复制失败
            this.close();
            try {
                copyDataBase();
            } catch (IOException e) {
                throw new Error("Error copying database");
            }
        }
    }

    private boolean checkDataBase(){
        SQLiteDatabase checkDB = null;
        try{
            File dbFile = new File(DB_PATH + DB_NAME);
            // 先判断文件是否存在,再尝试打开,减少异常触发
            if(dbFile.exists()){
                checkDB = SQLiteDatabase.openDatabase(dbFile.getAbsolutePath(), null, SQLiteDatabase.OPEN_READONLY);
            }
        }catch(SQLiteException e){
            //数据库不存在
        }
        if(checkDB != null){
            checkDB.close();
        }
        return checkDB != null;
    }

    private void copyDataBase() throws IOException{
        InputStream myInput = mContext.getAssets().open(DB_NAME);
        String outFileName = DB_PATH + DB_NAME;
        OutputStream myOutput = new FileOutputStream(outFileName);
        byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer))>0){
            myOutput.write(buffer, 0, length);
        }
        myOutput.flush();
        myOutput.close();
        myInput.close();
    }

    public void openDataBase() throws SQLException {
        String myPath = DB_PATH + DB_NAME;
        myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
    }

    @Override
    public synchronized void close() {
        if(myDataBase != null)
            myDataBase.close();
        super.close();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
    }

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

    public Cursor getData() {
        if(myDataBase == null || !myDataBase.isOpen()){
            throw new IllegalStateException("Database not open, call openDataBase() first");
        }
        return myDataBase.rawQuery("SELECT * FROM Categories WHERE CategoryID = 2", null);
    }
}

2. 修复MainActivity类

package com.example.cyberartillery;

import android.database.Cursor;
import android.database.SQLException;
import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.widget.Toast;

import java.io.IOException;

public class MainActivity extends Activity {

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

        // 去掉重复初始化逻辑
        DataBaseHelper myDbHelper = new DataBaseHelper(this);

        try {
            myDbHelper.createDataBase();
        } catch (IOException ioe) {
            throw new Error("Unable to create database");
        }

        try {
            myDbHelper.openDataBase();
        }catch(SQLException sqle){
            throw sqle;
        }

        // 正确处理查询游标
        Cursor cursor = null;
        try {
            cursor = myDbHelper.getData();
            if(cursor.moveToFirst()){
                // 示例:读取分类名称,字段名要和你实际数据库里的一致
                String categoryName = cursor.getString(cursor.getColumnIndexOrThrow("CategoryName"));
                Toast.makeText(this, "查询到的分类:" + categoryName, Toast.LENGTH_SHORT).show();
                // 这里可以把数据赋值给TextView等控件展示
            }else{
                Toast.makeText(this, "未查询到对应数据", Toast.LENGTH_SHORT).show();
            }
        }catch (Exception e){
            e.printStackTrace();
            Toast.makeText(this, "查询失败:" + e.getMessage(), Toast.LENGTH_SHORT).show();
        }finally {
            // 一定要关闭游标,避免内存泄漏
            if(cursor != null && !cursor.isClosed()){
                cursor.close();
            }
            // 如果其他页面还要用数据库,可以把关闭逻辑放到onDestroy方法里
            myDbHelper.close();
        }


        findViewById(R.id.MainImage1).setClickable(true);
        findViewById(R.id.MainImage1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (v.getId() == R.id.MainImage1) {
                    // 自定义点击逻辑
                }
            }
        });

    }
}

额外注意事项

  • 请确认你assets目录下确实存在northwind数据库文件,文件后缀不要写错
  • 请确认数据库里确实存在Categories表,以及CategoryID、CategoryName等你用到的字段名正确,大小写也要匹配
  • 测试前请先卸载旧应用,把之前错误生成的数据库文件清空,避免旧文件干扰

内容的提问来源于stack exchange,提问作者Movses Movsisyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 13:54:01